2 // getapt.cxx -- generate airport scenery from the given definition file
4 // Written by Curtis Olson, started September 1998.
6 // Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 // (Log is kept at end of this file)
26 #include <string> // Standard C++ string library
28 #include "Include/fg_stl_config.h"
30 #ifdef NEEDNAMESPACESTD
34 #include <Debug/fg_debug.h>
35 // #include <Include/fg_types.h>
36 #include <Math/fg_geodesy.h>
37 #include <Math/mat3.h>
38 #include <Math/point3d.hxx>
39 #include <Math/polar3d.hxx>
40 #include <Misc/fgstream.hxx>
41 #include <Objects/material.hxx>
43 // #include <gpc/gpc.h>
48 typedef vector < Point3D > container;
49 typedef container::iterator iterator;
50 typedef container::const_iterator const_iterator;
54 // Calculate distance between to Point3D's
55 static double calc_dist(const Point3D& p1, const Point3D& p2) {
60 return sqrt(x*x + y*y + z*z);
65 // convert a geodetic point lon(radians), lat(radians), elev(meter) to
67 static Point3D geod_to_cart(const Point3D& geod) {
70 double gc_lon, gc_lat, sl_radius;
72 // printf("A geodetic point is (%.2f, %.2f, %.2f)\n",
73 // geod[0], geod[1], geod[2]);
76 fgGeodToGeoc(geod.lat(), geod.radius(), &sl_radius, &gc_lat);
78 // printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon,
79 // gc_lat, sl_radius+geod[2]);
81 pp.setvals(gc_lon, gc_lat, sl_radius + geod.radius());
82 cp = fgPolarToCart3d(pp);
84 // printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z);
89 #define FG_APT_BASE_TEX_CONSTANT 2000.0
92 // Calculate texture coordinates for a given point.
94 calc_tex_coords(const fgPoint3d& p) {
97 cout << "Texture coordinates = " <<
98 FG_APT_BASE_TEX_CONSTANT * p.lon << " " <<
99 FG_APT_BASE_TEX_CONSTANT * p.lat << "\n";
101 tex.x = fmod(FG_APT_BASE_TEX_CONSTANT * p.lon, 10.0);
102 tex.y = fmod(FG_APT_BASE_TEX_CONSTANT * p.lat, 10.0);
112 cout << "Texture coordinates = " << tex.x << " " << tex.y << "\n";
119 // Calculate texture coordinates for a given point.
120 static Point3D calc_tex_coords(double *node, const Point3D& ref) {
124 cp.setvals( node[0] + ref.x(), node[1] + ref.y(), node[2] + ref.z() );
126 pp = fgCartToPolar3d(cp);
128 pp.setx( fmod(FG_APT_BASE_TEX_CONSTANT * pp.x(), 10.0) );
129 pp.sety( fmod(FG_APT_BASE_TEX_CONSTANT * pp.y(), 10.0) );
131 if ( pp.x() < 0.0 ) {
132 pp.setx( pp.x() + 10.0 );
135 if ( pp.y() < 0.0 ) {
136 pp.sety( pp.y() + 10.0 );
143 // generate the actual base area for the airport
145 gen_base( const Point3D& average, const container& perimeter, fgTILE *t)
148 Point3D cart, cart_trans, tex;
150 double dist, max_dist, temp;
157 cout << "generating airport base for size = " << perimeter.size() << "\n";
160 fragment.tile_ptr = t;
162 // find airport base material in the properties list
163 if ( ! material_mgr.find( APT_BASE_MATERIAL, fragment.material_ptr )) {
164 fgPrintf( FG_TERRAIN, FG_ALERT,
165 "Ack! unknown material name = %s in fgAptGenerat()\n",
169 printf(" tile center = %.2f %.2f %.2f\n",
170 t->center.x(), t->center.y(), t->center.z() );
171 printf(" airport center = %.2f %.2f %.2f\n",
172 average.x(), average.y(), average.z());
173 fragment.center = average;
175 normal[0] = average.x();
176 normal[1] = average.y();
177 normal[2] = average.z();
178 MAT3_NORMALIZE_VEC(normal, temp);
180 display_list = xglGenLists(1);
181 xglNewList(display_list, GL_COMPILE);
182 xglBegin(GL_TRIANGLE_FAN);
184 // first point center of fan
185 cart_trans = average - t->center;
186 t->nodes[t->ncount][0] = cart_trans.x();
187 t->nodes[t->ncount][1] = cart_trans.y();
188 t->nodes[t->ncount][2] = cart_trans.z();
189 center_num = t->ncount;
192 tex = calc_tex_coords( t->nodes[t->ncount-1], t->center );
193 xglTexCoord2f(tex.x(), tex.y());
194 xglNormal3dv(normal);
195 xglVertex3dv(t->nodes[t->ncount-1]);
197 // first point on perimeter
198 const_iterator current = perimeter.begin();
199 cart = geod_to_cart( *current );
200 cart_trans = cart - t->center;
201 t->nodes[t->ncount][0] = cart_trans.x();
202 t->nodes[t->ncount][1] = cart_trans.y();
203 t->nodes[t->ncount][2] = cart_trans.z();
207 tex = calc_tex_coords( t->nodes[i], t->center );
208 dist = distance3D(average, cart);
209 if ( dist > max_dist ) {
212 xglTexCoord2f(tex.x(), tex.y());
213 xglVertex3dv(t->nodes[i]);
217 const_iterator last = perimeter.end();
218 for ( ; current != last; ++current ) {
219 cart = geod_to_cart( *current );
220 cart_trans = cart - t->center;
221 t->nodes[t->ncount][0] = cart_trans.x();
222 t->nodes[t->ncount][1] = cart_trans.y();
223 t->nodes[t->ncount][2] = cart_trans.z();
225 fragment.add_face(center_num, i - 1, i);
227 tex = calc_tex_coords( t->nodes[i], t->center );
228 dist = distance3D(average, cart);
229 if ( dist > max_dist ) {
232 xglTexCoord2f(tex.x(), tex.y());
233 xglVertex3dv(t->nodes[i]);
237 // last point (first point in perimeter list)
238 current = perimeter.begin();
239 cart = geod_to_cart( *current );
240 cart_trans = cart - t->center;
241 fragment.add_face(center_num, i - 1, 1);
243 tex = calc_tex_coords( t->nodes[1], t->center );
244 xglTexCoord2f(tex.x(), tex.y());
245 xglVertex3dv(t->nodes[1]);
250 fragment.bounding_radius = max_dist;
251 fragment.display_list = display_list;
253 t->fragment_list.push_back(fragment);
257 // Load a .apt file and register the GL fragments with the
258 // corresponding tile
260 fgAptGenerate(const string& path, fgTILE *tile)
263 string apt_id, apt_name;
267 // face list (this indexes into the master tile vertex list)
270 double avex = 0.0, avey = 0.0, avez = 0.0;
273 // gpc_vertex p_2d, list_2d[MAX_PERIMETER];
274 // gpc_vertex_list perimeter_2d;
276 fg_gzifstream in( path );
278 // exit immediately assuming an airport file for this tile
285 // read in each line of the file
289 in.stream() >> token;
291 if ( token == "a" ) {
292 // airport info record (start of airport)
294 if ( apt_id != "" ) {
295 // we have just finished reading and airport record.
297 gen_base(average, perimeter, tile);
300 cout << "Reading airport record\n";
301 in.stream() >> apt_id;
304 avex = avey = avez = 0.0;
305 perimeter.erase( perimeter.begin(), perimeter.end() );
306 // skip to end of line.
307 while ( in.get(c) && c != '\n' ) {
310 cout << "\tID = " + apt_id + " Name = " + apt_name + "\n";
311 } else if ( token == "p" ) {
312 // airport area bounding polygon coordinate. These
313 // specify a convex hull that should already have been cut
314 // out of the base terrain. The points are given in
315 // counter clockwise order and are specified in lon/lat
318 avex += tile->nodes[i][0];
319 avey += tile->nodes[i][1];
320 avez += tile->nodes[i][2];
321 perimeter.push_back(p);
323 } else if ( token == "r" ) {
326 while ( in.get(c) && c != '\n' );
329 // airports.insert(a);
333 if ( apt_id != "" ) {
334 // we have just finished reading and airport record.
336 size = perimeter.size();
337 average.setvals( avex / (double)size + tile->center.x(),
338 avey / (double)size + tile->center.y(),
339 avez / (double)size + tile->center.z() );
341 gen_base(average, perimeter, tile);
349 // Revision 1.4 1998/10/16 00:51:46 curt
350 // Converted to Point3D class.
352 // Revision 1.3 1998/09/21 20:55:00 curt
353 // Used the cartesian form of the airport area coordinates to determine the
356 // Revision 1.2 1998/09/14 12:44:30 curt
357 // Don't recalculate perimeter points since it is not likely that they will match
358 // exactly with the previously calculated points, which will leave an ugly gap
359 // around the airport area.
361 // Revision 1.1 1998/09/14 02:14:01 curt
362 // Initial revision of genapt.[ch]xx for generating airport scenery.