3
* Copyright (C) 2002 Fabien Chereau
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
#include <math.h> // fmod
30
#include "stel_utility.h"
31
#include "stellarium.h"
32
#include "translator.h"
33
#include "stellastro.h"
36
wstring StelUtility::stringToWstring(const string& s)
38
return Translator::UTF8stringToWstring(s);
42
string StelUtility::wstringToString(const wstring& ws)
44
// Get UTF-8 string length
45
size_t len = wcstombs(NULL, ws.c_str(), 0)+1;
47
char* s = new char[len];
48
wcstombs(s, ws.c_str(), len);
54
wstring StelUtility::doubleToWstring(double d)
56
std::wostringstream woss;
61
wstring StelUtility::intToWstring(int i)
63
std::wostringstream woss;
68
double StelUtility::hms_to_rad( unsigned int h, unsigned int m, double s )
70
return (double)M_PI/24.*h*2.+(double)M_PI/12.*m/60.+s*M_PI/43200.;
73
double StelUtility::dms_to_rad(int d, int m, double s)
75
return (double)M_PI/180.*d+(double)M_PI/10800.*m+s*M_PI/648000.;
78
double hms_to_rad(unsigned int h, double m)
80
return (double)M_PI/24.*h*2.+(double)M_PI/12.*m/60.;
83
double dms_to_rad(int d, double m)
85
double t = (double)M_PI/180.*d+(double)M_PI/10800.*m;
90
void sphe_to_rect(double lng, double lat, Vec3d& v)
92
const double cosLat = cos(lat);
93
v.set(cos(lng) * cosLat, sin(lng) * cosLat, sin(lat));
96
void sphe_to_rect(double lng, double lat, double r, Vec3d& v)
98
const double cosLat = cos(lat);
99
v.set(cos(lng) * cosLat * r, sin(lng) * cosLat * r, sin(lat) * r);
102
void sphe_to_rect(float lng, float lat, Vec3f& v)
104
const double cosLat = cos(lat);
105
v.set(cos(lng) * cosLat, sin(lng) * cosLat, sin(lat));
108
void rect_to_sphe(double *lng, double *lat, const Vec3d& v)
110
double r = v.length();
112
*lng = atan2(v[1],v[0]);
115
void rect_to_sphe(float *lng, float *lat, const Vec3f& v)
117
double r = v.length();
119
*lng = atan2(v[1],v[0]);
123
// Obtains a Vec3f from a string with the form x,y,z
124
Vec3f StelUtility::str_to_vec3f(const string& s)
127
if (s.empty() || (sscanf(s.c_str(),"%f,%f,%f",&x, &y, &z)!=3)) return Vec3f(0.f,0.f,0.f);
131
// Obtains a string from a Vec3f with the form x,y,z
132
string StelUtility::vec3f_to_str(const Vec3f& v)
135
os << v[0] << "," << v[1] << "," << v[2];
139
// Provide the luminance in cd/m^2 from the magnitude and the surface in arcmin^2
140
float mag_to_luminance(float mag, float surface)
142
return expf(-0.4f * 2.3025851f * (mag - (-2.5f * log10f(surface)))) * 108064.73f;
145
// strips trailing whitespaces from buf.
146
#define iswhite(c) ((c)== ' ' || (c)=='\t')
147
static char *trim(char *x)
154
while (y >= x && iswhite(*y))
155
*y-- = 0; /* skip white space */
161
// salta espacios en blanco
162
static void skipwhite(char **s)
169
double get_dec_angle(const string& str)
171
const char* s = str.c_str();
172
char *mptr, *ptr, *dec, *hh;
174
char delim1[] = " :.,;DdHhMm'\n\t\xBA"; // 0xBA was old degree delimiter
175
char delim2[] = " NSEWnsew\"\n\t";
176
int dghh = 0, minutes = 0;
177
double seconds = 0.0, pos;
181
HOURS, DEGREES, LAT, LONG
184
if (s == NULL || !*s)
186
count = strlen(s) + 1;
187
if ((mptr = (char *) malloc(count)) == NULL)
190
memcpy(ptr, s, count);
194
/* the last letter has precedence over the sign */
195
if (strpbrk(ptr,"SsWw") != NULL)
198
if (*ptr == '+' || *ptr == '-')
199
negative = (char) (*ptr++ == '-' ? 1 : negative);
201
if ((hh = strpbrk(ptr,"Hh")) != NULL && hh < ptr + 3)
204
if (strpbrk(ptr,"SsNn") != NULL)
207
type = DEGREES; /* unspecified, the caller must control it */
209
if ((ptr = strtok(ptr,delim1)) != NULL)
217
if ((ptr = strtok(NULL,delim1)) != NULL)
219
minutes = atoi (ptr);
232
if ((ptr = strtok(NULL,delim2)) != NULL)
234
if ((dec = strchr(ptr,',')) != NULL)
236
seconds = strtod (ptr, NULL);
244
if ((ptr = strtok(NULL," \n\t")) != NULL)
247
if (*ptr == 'S' || *ptr == 'W' || *ptr == 's' || *ptr == 'w') negative = 1;
252
pos = ((dghh*60+minutes)*60 + seconds) / 3600.0;
253
if (type == HOURS && pos > 24.0)
255
if (type == LAT && pos > 90.0)
271
//! @brief Print the passed angle with the format dd°mm'ss(.ss)"
272
//! @param angle Angle in radian
273
//! @param decimal Define if 2 decimal must also be printed
274
//! @param useD Define if letter "d" must be used instead of °
275
//! @return The corresponding string
276
wstring StelUtility::printAngleDMS(double angle, bool decimals, bool useD)
281
// wchar_t degsign = L'°'; ???
282
wchar_t degsign = L'\u00B0';
283
if (useD) degsign = L'd';
293
int d = (int)(0.5+angle*(60*60*100));
294
const int centi = d % 100;
296
const int s = d % 60;
298
const int m = d % 60;
304
L"%lc%.2d%lc%.2d'%.2d.%02d\"",
305
sign, d, degsign, m, s, centi);
307
int d = (int)(0.5+angle*(60*60));
308
const int s = d % 60;
310
const int m = d % 60;
316
L"%lc%.2d%lc%.2d'%.2d\"",
317
sign, d, degsign, m, s);
322
//! @brief Print the passed angle with the format +hhhmmmss(.ss)"
323
//! @param angle Angle in radian
324
//! @param decimals Define if 2 decimal must also be printed
325
//! @return The corresponding string
326
wstring StelUtility::printAngleHMS(double angle, bool decimals)
330
angle = fmod(angle,2.0*M_PI);
331
if (angle < 0.0) angle += 2.0*M_PI; // range: [0..2.0*M_PI)
332
angle *= 12./M_PI; // range: [0..24)
334
angle = 0.5+angle*(60*60*100); // range:[0.5,24*60*60*100+0.5)
335
if (angle >= (24*60*60*100)) angle -= (24*60*60*100);
337
const int centi = h % 100;
339
const int s = h % 60;
341
const int m = h % 60;
347
L"%.2dh%.2dm%.2d.%02ds",h,m,s,centi);
349
angle = 0.5+angle*(60*60); // range:[0.5,24*60*60+0.5)
350
if (angle >= (24*60*60)) angle -= (24*60*60);
352
const int s = h % 60;
354
const int m = h % 60;
360
L"%.2dh%.2dm%.2ds",h,m,s);
366
// convert string int ISO 8601-like format [+/-]YYYY-MM-DDThh:mm:ss (no timzone offset)
369
int string_to_jday(string date, double &jd)
372
int year, month, day, hour, minute, second;
373
year = month = day = hour = minute = second = 0;
375
std::istringstream dstr( date );
377
// TODO better error checking
378
dstr >> year >> tmp >> month >> tmp >> day >> tmp >> hour >> tmp >> minute >> tmp >> second;
380
// cout << year << " " << month << " " << day << " " << hour << " " << minute << " " << second << endl;
382
// bounds checking (per s_tui time object)
383
if( year > 100000 || year < -100000 ||
384
month < 1 || month > 12 ||
385
day < 1 || day > 31 ||
386
hour < 0 || hour > 23 ||
387
minute < 0 || minute > 59 ||
388
second < 0 || second > 59) return 0;
391
// code taken from s_tui.cpp
398
// Correct for the lost days in Oct 1582 when the Gregorian calendar
399
// replaced the Julian calendar.
401
if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15))))
403
B = year / 400 - year / 100;
406
jd = ((floor(365.25 * year) +
407
floor(30.6001 * (month + 1)) + B + 1720996.5 +
408
day + hour / 24.0 + minute / 1440.0 + second / 86400.0));
415
double str_to_double(string str)
418
if(str=="") return 0;
420
std::istringstream dstr( str );
427
double str_to_pos_double(string str)
430
if(str=="") return 0;
432
std::istringstream dstr( str );
435
if(dbl < 0 ) dbl *= -1;
440
int str_to_int(string str)
443
if(str=="") return 0;
445
std::istringstream istr( str );
452
int str_to_int(string str, int default_value)
455
if(str=="") return default_value;
457
std::istringstream istr( str );
463
string double_to_str(double dbl)
466
std::ostringstream oss;
472
long int str_to_long(string str)
475
if(str=="") return 0;
477
std::istringstream istr( str );
483
int fcompare(const string& _base, const string& _sub)
486
while (i < _sub.length())
488
if (toupper(_base[i]) == toupper(_sub[i])) i++;
494
int fcompare(const wstring& _base, const wstring& _sub)
497
while (i < _sub.length())
499
if (toupper(_base[i]) == toupper(_sub[i])) i++;
506
// Return the time zone name taken from system locale
507
wstring StelUtility::get_time_zone_name_from_system(double JD)
509
// Windows will crash if date before 1970
510
// And no changes on Linux before that year either
511
// TODO: ALSO, on Win XP timezone never changes anyway???
512
if(JD < 2440588 ) JD = 2440588;
514
// The timezone name depends on the day because of the summer time
515
time_t rawtime = get_time_t_from_julian(JD);
517
struct tm * timeinfo;
518
timeinfo = localtime(&rawtime);
519
static char timez[255];
521
StelUtility::my_strftime(timez, 254, "%Z", timeinfo);
522
return StelUtility::stringToWstring(timez);
526
// Return the number of hours to add to gmt time to get the local time in day JD
527
// taking the parameters from system. This takes into account the daylight saving
528
// time if there is. (positive for Est of GMT)
529
// TODO : %z in strftime only works on GNU compiler
530
// Fixed 31-05-2004 Now use the extern variables set by tzset()
531
float StelUtility::get_GMT_shift_from_system(double JD, bool _local)
533
/* Doesn't seem like MACOSX is a special case... ??? rob
534
#if defined( MACOSX ) || defined(WIN32)
536
time_t rawtime; time(&rawtime);
537
timeinfo = localtime(&rawtime);
538
return (float)timeinfo->tm_gmtoff/3600 + (timeinfo->tm_isdst!=0);
541
#if !defined(MINGW32)
543
struct tm * timeinfo;
549
get_tm_from_julian(JD, &rawtime);
552
time_t ltime = timegm(&rawtime);
554
// This does not work
555
time_t ltime = my_timegm(&rawtime);
558
timeinfo = localtime(<ime);
561
rtime = get_time_t_from_julian(JD);
562
timeinfo = localtime(&rtime);
565
static char heure[20];
568
my_strftime(heure, 19, "%z", timeinfo);
569
// cout << heure << endl;
571
//cout << timezone << endl;
574
float min = 1.f/60.f * atoi(&heure[3]);
576
return min + atoi(heure);
581
timeinfo = localtime(&rawtime);
582
return -(float)timezone/3600 + (timeinfo->tm_isdst!=0);
586
// Return the time in ISO 8601 format that is : %Y-%m-%d %H:%M:%S
587
string StelUtility::get_ISO8601_time_UTC(double JD)
590
get_tm_from_julian(JD, &time_utc);
592
static char isotime[255];
593
my_strftime(isotime, 254, "%Y-%m-%d %H:%M:%S", &time_utc);