]> git.mxchange.org Git - simgear.git/blob - simgear/timing/timezone.cxx
Collapse SGGeoCoord into SGTimeZone, and switch timezone search to cartesian math.
[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 #include <errno.h>
30 #include <string.h>
31 #include <stdio.h>
32
33 #include <simgear/structure/exception.hxx>
34
35 #include "timezone.h"
36
37 SGTimeZone::SGTimeZone(const SGGeod& geod, char* cc, char* desc) :
38     centerpoint(SGVec3d::fromGeod(geod))
39
40     countryCode = cc;
41     descriptor = desc;
42 }
43
44 /* Build a timezone object from a textline in zone.tab */
45 SGTimeZone::SGTimeZone(const char *infoString)
46 {
47     double lat = 0.0, lon = 0.0;
48     
49     int i = 0;
50     while (infoString[i] != '\t')
51         i++;
52     char buffer[128];
53     char latlon[128];
54     strncpy(buffer, infoString, i);
55     buffer[i] = 0;
56     countryCode = buffer;
57     i ++;
58     int start = i;
59     while (infoString[i] != '\t') {
60         i++;
61     }
62     int size = i - start;
63     strncpy(latlon, (&infoString[start]), size);
64     latlon[size] = 0;
65     char sign;
66     sign = latlon[0];
67     strncpy(buffer, &latlon[1], 2);
68     buffer[2] = 0;
69     lat = atof(buffer);
70     strncpy(buffer, &latlon[3], 2);
71     buffer[2] = 0;
72     lat += (atof(buffer) / 60);
73     int nextPos;
74     if (strlen(latlon) > 12) {
75         nextPos = 7;
76         strncpy(buffer, &latlon[5], 2);
77         buffer[2] = 0;
78         lat += (atof(buffer) / 3600.0);
79     } else {
80         nextPos = 5;
81     }
82     if (sign == '-') {
83         lat = -lat;
84     }
85
86     sign = latlon[nextPos];
87     nextPos++;
88     strncpy(buffer, &latlon[nextPos], 3);
89     buffer[3] = 0;
90     lon = atof(buffer);
91     nextPos += 3;
92     strncpy(buffer, &latlon[nextPos], 2);
93     buffer[2] = 0;
94  
95     lon  += (atof(buffer) / 60);
96     if (strlen(latlon) > 12) {
97         nextPos += 2;
98         strncpy(buffer, &latlon[nextPos], 2); 
99         buffer[2] = 0;
100         lon +=  (atof (buffer) / 3600.00);
101     }
102     if (sign == '-') {
103         lon = -lon;
104     }
105     i ++;
106     start = i;
107     while (!((infoString[i] == '\t') || (infoString[i] == '\n'))) {
108         i++;
109     }
110     size = i - start;
111     strncpy(buffer, (&infoString[start]), size);
112     buffer[size] = 0;
113     descriptor = buffer;
114     
115     centerpoint = SGVec3d::fromGeod(SGGeod::fromDeg(lon, lat));
116 }
117
118 /* the copy constructor */
119 SGTimeZone::SGTimeZone(const SGTimeZone& other)
120 {
121     centerpoint = other.centerpoint;
122     countryCode = other.countryCode;
123     descriptor = other.descriptor;
124 }
125
126
127 /********* Member functions for SGTimeZoneContainer class ********/
128
129 SGTimeZoneContainer::SGTimeZoneContainer(const char *filename)
130 {
131     char buffer[256];
132     FILE* infile = fopen(filename, "rb");
133     if (!(infile)) {
134         string e = "Unable to open time zone file '";
135         throw sg_exception(e + filename + '\'');
136     }
137     
138     errno = 0;
139
140     while (1) {
141         fgets(buffer, 256, infile);
142         if (feof(infile)) {
143             break;
144         }
145         for (char *p = buffer; *p; p++) {
146             if (*p == '#') {
147                 *p = 0;
148                 break;
149             }    
150         }
151         if (buffer[0]) {
152             zones.push_back(new SGTimeZone(buffer));
153         }
154     }
155     if ( errno ) {
156         perror( "SGTimeZoneContainer()" );
157         errno = 0;
158     }
159     
160     fclose(infile);
161 }
162
163 SGTimeZoneContainer::~SGTimeZoneContainer()
164 {
165   TZVec::iterator it = zones.begin();
166   for (; it != zones.end(); ++it) {
167     delete *it;
168   }
169 }
170
171 SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
172 {
173   SGVec3d refCart(SGVec3d::fromGeod(ref));
174   SGTimeZone* match = NULL;
175   double minDist2 = HUGE_VAL;
176   
177   TZVec::const_iterator it = zones.begin();
178   for (; it != zones.end(); ++it) {
179     double d2 = distSqr((*it)->cartCenterpoint(), refCart);
180     if (d2 < minDist2) {
181       match = *it;
182       minDist2 = d2;
183     }
184   }
185
186   return match;
187 }
188