]> git.mxchange.org Git - flightgear.git/blob - GenAirports/main.cxx
Modified to adhere to new polygon naming convention, and also to read the
[flightgear.git] / GenAirports / main.cxx
1 // main.cxx -- main loop
2 //
3 // Written by Curtis Olson, started March 1998.
4 //
5 // Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22 // (Log is kept at end of this file)
23 //
24
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <Include/compiler.h>
31
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h>
34 #endif
35
36 #include <list>
37 #include <stdio.h>
38 #include <string.h>
39 #include STL_STRING
40
41 #include <Bucket/newbucket.hxx>
42 #include <Debug/logstream.hxx>
43 #include <Include/fg_constants.h>
44 #include <Misc/fgstream.hxx>
45 #include <Polygon/index.hxx>
46
47 #include "area.hxx"
48 #include "convex_hull.hxx"
49
50
51 // write out airport data
52 void write_airport( int p_index, list_container hull_list, FGBucket b, 
53                     const string& root, const bool cut_and_keep ) {
54     char tile_name[256], poly_index[256];
55
56     long int b_index = b.gen_index();
57     string base = b.gen_base_path();
58     string path = root + "/Scenery/" + base;
59     string command = "mkdir -p " + path;
60     system( command.c_str() );
61
62     sprintf(tile_name, "%ld", b_index);
63     string aptfile = path + "/" + tile_name;
64
65     sprintf( poly_index, "%d", p_index );
66     aptfile += ".";
67     aptfile += poly_index;
68     cout << "apt file = " << aptfile << endl;
69
70     FILE *fd;
71     if ( (fd = fopen(aptfile.c_str(), "a")) == NULL ) {
72         cout << "Cannot open file: " << aptfile << endl;
73         exit(-1);
74     }
75
76     if ( cut_and_keep ) {
77         fprintf( fd, "AirportKeep\n" );
78     } else {
79         fprintf( fd, "AirportIgnore\n" );
80     }
81     fprintf( fd, "%d\n", hull_list.size() );
82     // write perimeter polygon
83     list_iterator current = hull_list.begin();
84     list_iterator last = hull_list.end();
85     for ( ; current != last ; ++current ) {
86         fprintf( fd, "%.7f %.7f\n", (*current).lon, (*current).lat );
87     }
88
89     fclose(fd);
90 }
91
92
93 // process and airport + runway list
94 void process_airport( string airport, list < string > & runway_list,
95                       const string& root ) {
96     list_container rwy_list, apt_list, hull_list;
97     list_iterator current, last;
98
99     // parse main airport information
100     int elev;
101
102     cout << airport << endl;
103     string apt_type = airport.substr(0, 1);
104     string apt_code = airport.substr(2, 4);
105     string apt_lat = airport.substr(7, 10);
106     string apt_lon = airport.substr(18, 11);
107     string apt_elev = airport.substr(30, 5);
108     sscanf( apt_elev.c_str(), "%d", &elev );
109     string apt_use = airport.substr(36, 1);
110     string apt_twr = airport.substr(37, 1);
111     string apt_bldg = airport.substr(38, 1);
112     string apt_name = airport.substr(40);
113
114     /*
115     cout << "  type = " << apt_type << endl;
116     cout << "  code = " << apt_code << endl;
117     cout << "  lat  = " << apt_lat << endl;
118     cout << "  lon  = " << apt_lon << endl;
119     cout << "  elev = " << apt_elev << " " << elev << endl;
120     cout << "  use  = " << apt_use << endl;
121     cout << "  twr  = " << apt_twr << endl;
122     cout << "  bldg = " << apt_bldg << endl;
123     cout << "  name = " << apt_name << endl;
124     */
125
126     // parse runways and generate the vertex list
127     string rwy_str;
128     double lon, lat, hdg;
129     int len, width;
130
131     list < string >::iterator last_runway = runway_list.end();
132     for ( list < string >::iterator current_runway = runway_list.begin();
133           current_runway != last_runway ; ++current_runway ) {
134         rwy_str = (*current_runway);
135
136         cout << rwy_str << endl;
137         string rwy_no = rwy_str.substr(2, 4);
138         string rwy_lat = rwy_str.substr(6, 10);
139         sscanf( rwy_lat.c_str(), "%lf", &lat);
140         string rwy_lon = rwy_str.substr(17, 11);
141         sscanf( rwy_lon.c_str(), "%lf", &lon);
142         string rwy_hdg = rwy_str.substr(29, 7);
143         sscanf( rwy_hdg.c_str(), "%lf", &hdg);
144         string rwy_len = rwy_str.substr(36, 7);
145         sscanf( rwy_len.c_str(), "%d", &len);
146         string rwy_width = rwy_str.substr(43, 4);
147         sscanf( rwy_width.c_str(), "%d", &width);
148         string rwy_sfc = rwy_str.substr(47, 4);
149         string rwy_end1 = rwy_str.substr(52, 6);
150         string rwy_end2 = rwy_str.substr(59, 6);
151
152         /*
153         cout << "  no    = " << rwy_no << endl;
154         cout << "  lat   = " << rwy_lat << " " << lat << endl;
155         cout << "  lon   = " << rwy_lon << " " << lon << endl;
156         cout << "  hdg   = " << rwy_hdg << " " << hdg << endl;
157         cout << "  len   = " << rwy_len << " " << len << endl;
158         cout << "  width = " << rwy_width << " " << width << endl;
159         cout << "  sfc   = " << rwy_sfc << endl;
160         cout << "  end1  = " << rwy_end1 << endl;
161         cout << "  end2  = " << rwy_end2 << endl;
162         */
163         
164         rwy_list = gen_runway_area( lon, lat, hdg * DEG_TO_RAD, 
165                                     (double)len * FEET_TO_METER,
166                                     (double)width * FEET_TO_METER );
167
168         // add rwy_list to apt_list
169         current = rwy_list.begin();
170         last = rwy_list.end();
171         for ( ; current != last ; ++current ) {
172             apt_list.push_back(*current);
173         }
174     }
175
176     if ( apt_list.size() == 0 ) {
177         cout << "no runway points generated" << endl;
178         return;
179     }
180
181     // printf("Runway points in degrees\n");
182     // current = apt_list.begin();
183     // last = apt_list.end();
184     // for ( ; current != last; ++current ) {
185     //   printf( "%.5f %.5f\n", current->lon, current->lat );
186     // }
187     // printf("\n");
188
189     // generate convex hull
190     hull_list = convex_hull(apt_list);
191
192     // get next polygon index
193     int index = poly_index_next();
194
195     // find average center, min, and max point of convex hull
196     point2d average, min, max;
197     double sum_x, sum_y;
198     int count = hull_list.size();
199     current = hull_list.begin();
200     last = hull_list.end();
201     sum_x = sum_y = 0.0;
202     min.x = min.y = 200.0;
203     max.x = max.y = -200.0;
204     for ( ; current != last; ++current ) {
205         // printf("return = %.6f %.6f\n", (*current).x, (*current).y);
206         sum_x += (*current).x;
207         sum_y += (*current).y;
208
209         if ( (*current).x < min.x ) { min.x = (*current).x; }
210         if ( (*current).y < min.y ) { min.y = (*current).y; }
211         if ( (*current).x > max.x ) { max.x = (*current).x; }
212         if ( (*current).y > max.y ) { max.y = (*current).y; }
213     }
214     average.x = sum_x / count;
215     average.y = sum_y / count;
216
217     // find buckets for center, min, and max points of convex hull.
218     // note to self: self, you should think about checking for runways
219     // that span the data line
220     FGBucket b(average.lon, average.lat);
221     FGBucket b_min(min.x, min.y);
222     FGBucket b_max(max.x, max.y);
223     cout << "Bucket center = " << b << endl;
224     cout << "Bucket min = " << b_min << endl;
225     cout << "Bucket max = " << b_max << endl;
226     
227     if ( b_min == b_max ) {
228         write_airport( index, hull_list, b, root, true );
229     } else {
230         FGBucket b_cur;
231         int dx, dy, i, j;
232
233         fgBucketDiff(b_min, b_max, &dx, &dy);
234         cout << "airport spans tile boundaries" << endl;
235         cout << "  dx = " << dx << "  dy = " << dy << endl;
236
237         if ( (dx > 1) || (dy > 1) ) {
238             cout << "somethings really wrong!!!!" << endl;
239             exit(-1);
240         }
241
242         for ( j = 0; j <= dy; j++ ) {
243             for ( i = 0; i <= dx; i++ ) {
244                 b_cur = fgBucketOffset(min.x, min.y, i, j);
245                 if ( b_cur == b ) {
246                     write_airport( index, hull_list, b_cur, root, true );
247                 } else {
248                     write_airport( index, hull_list, b_cur, root, false );
249                 }
250             }
251         }
252         // string answer; cin >> answer;
253     }
254 }
255
256
257 // reads the apt_full file and extracts and processes the individual
258 // airport records
259 int main( int argc, char **argv ) {
260     list < string > runway_list;
261     string airport, last_airport;
262     string line;
263     char tmp[256];
264
265     fglog().setLogLevels( FG_ALL, FG_DEBUG );
266
267     if ( argc != 3 ) {
268         FG_LOG( FG_GENERAL, FG_ALERT, 
269                 "Usage " << argv[0] << " <apt_file> <work_dir>" );
270         exit(-1);
271     }
272
273     // make work directory
274     string work_dir = argv[2];
275     string command = "mkdir -p " + work_dir;
276     system( command.c_str() );
277
278     // initialize persistant polygon counter
279     string counter_file = work_dir + "/polygon.counter";
280     poly_index_init( counter_file );
281
282     fg_gzifstream in( argv[1] );
283     if ( !in ) {
284         FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << argv[1] );
285         exit(-1);
286     }
287
288     // throw away the first 3 lines
289     in.getline(tmp, 256);
290     in.getline(tmp, 256);
291     in.getline(tmp, 256);
292
293     last_airport = "";
294
295     while ( ! in.eof() ) {
296         in.getline(tmp, 256);
297         line = tmp;
298         // cout << line << endl;
299
300         if ( line.length() == 0 ) {
301             // empty, skip
302         } else if ( line[0] == '#' ) {
303             // comment, skip
304         } else if ( (line[0] == 'A') || (line[0] == 'S') ) {
305             // start of airport record
306             airport = line;
307
308             if ( last_airport.length() ) {
309                 // process previous record
310                 process_airport(last_airport, runway_list, argv[2]);
311             }
312
313             // clear runway list for start of next airport
314             runway_list.erase(runway_list.begin(), runway_list.end());
315
316             last_airport = airport;
317         } else if ( line[0] == 'R' ) {
318             // runway entry
319             runway_list.push_back(line);
320         } else if ( line == "99" ) {
321             // end of file
322             break;
323         } else {
324             FG_LOG( FG_GENERAL, FG_ALERT, 
325                     "Unknown line in file" << endl << line );
326             exit(-1);
327         }
328     }
329
330     if ( last_airport.length() ) {
331         // process previous record
332         process_airport(last_airport, runway_list, argv[2]);
333     }
334
335     return 0;
336 }
337
338
339 // $Log$
340 // Revision 1.7  1999/02/25 21:32:49  curt
341 // Modified to adhere to new polygon naming convention, and also to read the
342 // new Robin Peel aiport format.
343 //
344 // Revision 1.6  1999/02/11 01:10:51  curt
345 // Start of scenery revamp project.
346 //
347 // Revision 1.5  1998/09/17 18:40:43  curt
348 // Debug message tweaks.
349 //
350 // Revision 1.4  1998/09/09 20:59:56  curt
351 // Loop construct tweaks for STL usage.
352 // Output airport file to be used to generate airport scenery on the fly
353 //   by the run time sim.
354 //
355 //