1 /***************************************************************************
2 dms.cpp - K Desktop Planetarium
4 begin : Sun Feb 11 2001
5 copyright : (C) 2001 by Jason Harris
6 email : jharris@30doradus.org
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
25 void dms::setD( const double &x
) {
31 void dms::setD(const int &d
, const int &m
, const int &s
, const int &ms
) {
32 D
= (double)abs(d
) + ((double)m
+ ((double)s
+ (double)ms
/1000.)/60.)/60.;
33 if (d
<0) {D
= -1.0*D
;}
38 void dms::setH( const double &x
) {
42 void dms::setH(const int &h
, const int &m
, const int &s
, const int &ms
) {
43 D
= 15.0*((double)abs(h
) + ((double)m
+ ((double)s
+ (double)ms
/1000.)/60.)/60.);
44 if (h
<0) {D
= -1.0*D
;}
49 void dms::setRadians( const double &Rad
) {
54 bool dms::setFromString( const QString
&str
, bool isDeg
) {
57 bool checkValue( false ), badEntry( false ), negative( false );
58 QString entry
= str
.stripWhiteSpace();
60 //remove any instances of unit characters.
61 //h, d, m, s, ', ", or the degree symbol (ASCII 176)
62 entry
.replace( QRegExp("h"), "" );
63 entry
.replace( QRegExp("d"), "" );
64 entry
.replace( QRegExp("m"), "" );
65 entry
.replace( QRegExp("s"), "" );
67 sdeg
.sprintf("%c", 176);
68 entry
.replace( QRegExp(sdeg
), "" );
69 entry
.replace( QRegExp("\'"), "" );
70 entry
.replace( QRegExp("\""), "" );
72 //Account for localized decimal-point settings
73 //QString::toDouble() requires that the decimal symbol is "."
74 entry
.replace( KGlobal::locale()->decimalSymbol(), "." );
76 //empty entry returns false
77 if ( entry
.isEmpty() ) {
82 //try parsing a simple integer
83 d
= entry
.toInt( &checkValue
);
85 if (isDeg
) setD( d
, 0, 0 );
90 //try parsing a simple double
91 double x
= entry
.toDouble( &checkValue
);
93 if ( isDeg
) setD( x
);
98 //try parsing multiple fields.
101 //check for colon-delimiters or space-delimiters
102 if ( entry
.contains(':') )
103 fields
= QStringList::split( ':', entry
);
104 else fields
= QStringList::split( " ", entry
);
106 //anything with one field is invalid!
107 if ( fields
.count() == 1 ) {
112 //If two fields we will add a third one, and then parse with
113 //the 3-field code block. If field[1] is an int, add a third field equal to "0".
114 //If field[1] is a double, convert it to integer arcmin, and convert
115 //the remainder to integer arcsec
116 //If field[1] is neither int nor double, return false.
117 if ( fields
.count() == 2 ) {
118 m
= fields
[1].toInt( &checkValue
);
119 if ( checkValue
) fields
.append( QString( "0" ) );
121 double mx
= fields
[1].toDouble( &checkValue
);
123 fields
[1] = QString("%1").arg( int(mx
) );
124 fields
.append( QString("%1").arg( int( 60.0*(mx
- int(mx
)) ) ) );
132 //Now have (at least) three fields ( h/d m s );
133 //we can ignore anything after 3rd field
134 if ( fields
.count() >= 3 ) {
135 //See if first two fields parse as integers, and third field as a double
137 d
= fields
[0].toInt( &checkValue
);
138 if ( !checkValue
) badEntry
= true;
139 m
= fields
[1].toInt( &checkValue
);
140 if ( !checkValue
) badEntry
= true;
141 s
= fields
[2].toDouble( &checkValue
);
142 if ( !checkValue
) badEntry
= true;
144 //Special case: If first field is "-0", store the negative sign.
145 //(otherwise it gets dropped)
146 if ( fields
[0].at(0) == '-' && d
== 0 ) negative
= true;
150 double D
= (double)abs(d
) + (double)abs(m
)/60.
151 + (double)fabs(s
)/3600.;
153 if ( negative
|| d
<0 || m
< 0 || s
<0 ) { D
= -1.0*D
;}
168 const int dms::arcmin( void ) const {
169 int am
= int( 60.0*( fabs(D
) - abs( degree() ) ) );
170 if ( D
<0.0 && D
>-1.0 ) { //angle less than zero, but greater than -1.0
171 am
= -1*am
; //make minute negative
176 const int dms::arcsec( void ) const {
177 int as
= int( 60.0*( 60.0*( fabs(D
) - abs( degree() ) ) - abs( arcmin() ) ) );
178 //If the angle is slightly less than 0.0, give ArcSec a neg. sgn.
179 if ( degree()==0 && arcmin()==0 && D
<0.0 ) {
185 const int dms::marcsec( void ) const {
186 int as
= int( 1000.0*(60.0*( 60.0*( fabs(D
) - abs( degree() ) ) - abs( arcmin() ) ) - abs( arcsec() ) ) );
187 //If the angle is slightly less than 0.0, give ArcSec a neg. sgn.
188 if ( degree()==0 && arcmin()==0 && arcsec()== 0 && D
<0.0 ) {
194 const int dms::minute( void ) const {
195 int hm
= int( 60.0*( fabs( Hours() ) - abs( hour() ) ) );
196 if ( Hours()<0.0 && Hours()>-1.0 ) { //angle less than zero, but greater than -1.0
197 hm
= -1*hm
; //make minute negative
202 const int dms::second( void ) const {
203 int hs
= int( 60.0*( 60.0*( fabs( Hours() ) - abs( hour() ) ) - abs( minute() ) ) );
204 if ( hour()==0 && minute()==0 && Hours()<0.0 ) {
210 const int dms::msecond( void ) const {
211 int hs
= int( 1000.0*(60.0*( 60.0*( fabs( Hours() ) - abs( hour() ) ) - abs( minute() ) ) - abs( second() ) ) );
212 if ( hour()==0 && minute()==0 && second()==0 && Hours()<0.0 ) {
218 const double& dms::sin( void ) const {
227 const double& dms::cos( void ) const {
236 void dms::SinCos( double &sina
, double &cosa
) const {
237 /**We have two versions of this function. One is ANSI standard, but
238 *slower. The other is faster, but is GNU only.
239 *Using the __GLIBC_ and __GLIBC_MINOR_ constants to determine if the
240 * GNU extension sincos() is defined.
245 #if ( __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 )
247 sincos( radians(), &Sin
, &Cos
);
249 //For older GLIBC versions
250 Sin
= ::sin( radians() );
251 Cos
= ::cos( radians() );
254 //ANSI-compliant version
255 Sin
= ::sin( radians() );
256 Cos
= ::cos( radians() );
264 const double& dms::radians( void ) const {
266 Radians
= D
*DegToRad
;
273 const dms
dms::reduce( void ) const {
275 while (a
<0.0) {a
+= 360.0;}
276 while (a
>=360.0) {a
-= 360.0;}
280 const QString
dms::toDMSString(bool forceSign
) const {
283 int dd
= abs(degree());
284 int dm
= abs(arcmin());
285 int ds
= abs(arcsec());
287 if ( Degrees() < 0.0 ) pm
= '-';
288 else if (forceSign
&& Degrees() > 0.0 ) pm
= '+';
290 QString
format( "%c%3d%c %02d\' %02d\"" );
291 if ( dd
< 100 ) format
= "%c%2d%c %02d\' %02d\"";
292 if ( dd
< 10 ) format
= "%c%1d%c %02d\' %02d\"";
294 return dummy
.sprintf(format
.local8Bit(), pm
, dd
, 176, dm
, ds
);
297 const QString
dms::toHMSString() const {
299 return dummy
.sprintf("%02dh %02dm %02ds", hour(), minute(), second());
302 dms
dms::fromString(QString
& st
, bool deg
) {
306 ok
= result
.setFromString( st
, deg
);
311 // kdDebug() << i18n( "Could Not Set Angle from string: " ) << st << endl;
316 // M_PI is defined in math.h
317 const double dms::PI
= M_PI
;
318 const double dms::DegToRad
= PI
/180.0;