]> git.mxchange.org Git - simgear.git/blob - simgear/timing/timezone.cxx
Alas. Fix #pragma magic for GCC <= 4.5.
[simgear.git] / simgear / timing / timezone.cxx
1 /* -*- Mode: C++ -*- *****************************************************
2  * timezone.cc
3  * Written by Durk Talsma. Started July 1999.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Library General Public License for more details.
14  *
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  **************************************************************************/
20
21 /*************************************************************************
22  *
23  * SGTimeZone is derived from geocoord, and stores the timezone centerpoint,
24  * as well as the countrycode and the timezone descriptor. The latter is 
25  * used in order to get the local time. 
26  *
27  ************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 #  include <simgear_config.h>
31 #endif
32
33 #include <errno.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <cstdlib>
37
38 #include <simgear/structure/exception.hxx>
39
40 #include "timezone.h"
41
42 SGTimeZone::SGTimeZone(const SGGeod& geod, char* cc, char* desc) :
43     centerpoint(SGVec3d::fromGeod(geod))
44
45     countryCode = cc;
46     descriptor = desc;
47 }
48
49 /* Build a timezone object from a textline in zone.tab */
50 SGTimeZone::SGTimeZone(const char *infoString)
51 {
52     double lat = 0.0, lon = 0.0;
53     
54     int i = 0;
55     while (infoString[i] != '\t')
56         i++;
57     char buffer[128];
58     char latlon[128];
59     strncpy(buffer, infoString, i);
60     buffer[i] = 0;
61     countryCode = buffer;
62     i ++;
63     int start = i;
64     while (infoString[i] != '\t') {
65         i++;
66     }
67     int size = i - start;
68     strncpy(latlon, (&infoString[start]), size);
69     latlon[size] = 0;
70     char sign;
71     sign = latlon[0];
72     strncpy(buffer, &latlon[1], 2);
73     buffer[2] = 0;
74     lat = atof(buffer);
75     strncpy(buffer, &latlon[3], 2);
76     buffer[2] = 0;
77     lat += (atof(buffer) / 60);
78     int nextPos;
79     if (strlen(latlon) > 12) {
80         nextPos = 7;
81         strncpy(buffer, &latlon[5], 2);
82         buffer[2] = 0;
83         lat += (atof(buffer) / 3600.0);
84     } else {
85         nextPos = 5;
86     }
87     if (sign == '-') {
88         lat = -lat;
89     }
90
91     sign = latlon[nextPos];
92     nextPos++;
93     strncpy(buffer, &latlon[nextPos], 3);
94     buffer[3] = 0;
95     lon = atof(buffer);
96     nextPos += 3;
97     strncpy(buffer, &latlon[nextPos], 2);
98     buffer[2] = 0;
99  
100     lon  += (atof(buffer) / 60);
101     if (strlen(latlon) > 12) {
102         nextPos += 2;
103         strncpy(buffer, &latlon[nextPos], 2); 
104         buffer[2] = 0;
105         lon +=  (atof (buffer) / 3600.00);
106     }
107     if (sign == '-') {
108         lon = -lon;
109     }
110     i ++;
111     start = i;
112     while (!((infoString[i] == '\t') || (infoString[i] == '\n'))) {
113         i++;
114     }
115     size = i - start;
116     strncpy(buffer, (&infoString[start]), size);
117     buffer[size] = 0;
118     descriptor = buffer;
119     
120     centerpoint = SGVec3d::fromGeod(SGGeod::fromDeg(lon, lat));
121 }
122
123 /* the copy constructor */
124 SGTimeZone::SGTimeZone(const SGTimeZone& other)
125 {
126     centerpoint = other.centerpoint;
127     countryCode = other.countryCode;
128     descriptor = other.descriptor;
129 }
130
131
132 /********* Member functions for SGTimeZoneContainer class ********/
133
134 SGTimeZoneContainer::SGTimeZoneContainer(const char *filename)
135 {
136     char buffer[256];
137     FILE* infile = fopen(filename, "rb");
138     if (!(infile)) {
139         string e = "Unable to open time zone file '";
140         throw sg_exception(e + filename + '\'');
141     }
142     
143     errno = 0;
144
145     while (1) {
146         if (0 == fgets(buffer, 256, infile))
147             break;
148         if (feof(infile)) {
149             break;
150         }
151         for (char *p = buffer; *p; p++) {
152             if (*p == '#') {
153                 *p = 0;
154                 break;
155             }    
156         }
157         if (buffer[0]) {
158             zones.push_back(new SGTimeZone(buffer));
159         }
160     }
161     if ( errno ) {
162         perror( "SGTimeZoneContainer()" );
163         errno = 0;
164     }
165     
166     fclose(infile);
167 }
168
169 SGTimeZoneContainer::~SGTimeZoneContainer()
170 {
171   TZVec::iterator it = zones.begin();
172   for (; it != zones.end(); ++it) {
173     delete *it;
174   }
175 }
176
177 SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
178 {
179   SGVec3d refCart(SGVec3d::fromGeod(ref));
180   SGTimeZone* match = NULL;
181   double minDist2 = HUGE_VAL;
182   
183   TZVec::const_iterator it = zones.begin();
184   for (; it != zones.end(); ++it) {
185     double d2 = distSqr((*it)->cartCenterpoint(), refCart);
186     if (d2 < minDist2) {
187       match = *it;
188       minDist2 = d2;
189     }
190   }
191
192   return match;
193 }
194