first work on reading apt.dat 8.50
This commit is contained in:
parent
1eae25d17a
commit
0dddd26b91
36 changed files with 9430 additions and 1 deletions
|
@ -3,4 +3,5 @@ include_directories(${PROJECT_SOURCE_DIR}/src/BuildTiles)
|
|||
|
||||
if (NEWMAT_FOUND)
|
||||
add_subdirectory(GenAirports)
|
||||
endif (NEWMAT_FOUND)
|
||||
add_subdirectory(GenAirports850)
|
||||
endif (NEWMAT_FOUND)
|
||||
|
|
1
src/Airports/GenAirports850/.gitignore
vendored
Normal file
1
src/Airports/GenAirports850/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
genapts850
|
32
src/Airports/GenAirports850/CMakeLists.txt
Normal file
32
src/Airports/GenAirports850/CMakeLists.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
|
||||
add_executable(genapts850
|
||||
apt_surface.hxx apt_surface.cxx
|
||||
build.cxx build.hxx
|
||||
convex_hull.cxx convex_hull.hxx
|
||||
elevations.cxx elevations.hxx
|
||||
global.hxx
|
||||
lights.hxx lights.cxx
|
||||
main.cxx
|
||||
point2d.cxx point2d.hxx
|
||||
poly_extra.cxx poly_extra.hxx
|
||||
runway.cxx runway.hxx
|
||||
rwy_common.cxx rwy_common.hxx
|
||||
rwy_nonprec.cxx rwy_nonprec.hxx
|
||||
rwy_gen.cxx rwy_gen.hxx
|
||||
rwy_simple.cxx rwy_simple.hxx
|
||||
rwy_visual.cxx rwy_visual.hxx
|
||||
taxiway.cxx taxiway.hxx
|
||||
texparams.hxx
|
||||
)
|
||||
|
||||
target_link_libraries(genapts850
|
||||
Polygon Geometry
|
||||
Array Optimize Output poly2tri
|
||||
TriangleJRS
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GPC_LIBRARY}
|
||||
${NEWMAT_LIBRARY})
|
||||
|
||||
install(TARGETS genapts850 RUNTIME DESTINATION bin)
|
477
src/Airports/GenAirports850/apt_surface.cxx
Normal file
477
src/Airports/GenAirports850/apt_surface.cxx
Normal file
|
@ -0,0 +1,477 @@
|
|||
// apt_surface.cxx -- class to manage airport terrain surface
|
||||
// approximation and smoothing
|
||||
//
|
||||
// Written by Curtis Olson, started March 2003.
|
||||
//
|
||||
// Copyright (C) 2003 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: apt_surface.cxx,v 1.31 2005-12-19 16:51:25 curt Exp $
|
||||
//
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
// libnewmat includes and defines
|
||||
#define WANT_STREAM // include.h will get stream fns
|
||||
#define WANT_MATH // include.h will get math fns
|
||||
// newmatap.h will get include.h
|
||||
#include <newmat/newmatap.h> // need matrix applications
|
||||
#include <newmat/newmatio.h> // need matrix output routines
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include <Array/array.hxx>
|
||||
|
||||
#include "elevations.hxx"
|
||||
#include "global.hxx"
|
||||
#include "apt_surface.hxx"
|
||||
|
||||
|
||||
static bool limit_slope( SimpleMatrix *Pts, int i1, int j1, int i2, int j2,
|
||||
double average_elev_m )
|
||||
{
|
||||
bool slope_error = false;
|
||||
|
||||
Point3D p1, p2;
|
||||
p1 = Pts->element(i1,j1);
|
||||
p2 = Pts->element(i2,j2);
|
||||
|
||||
double az1, az2, dist;
|
||||
double slope;
|
||||
|
||||
geo_inverse_wgs_84( 0, p1.y(), p1.x(), p2.y(), p2.x(),
|
||||
&az1, &az2, &dist );
|
||||
slope = (p2.z() - p1.z()) / dist;
|
||||
|
||||
if ( fabs(slope) > (slope_max + slope_eps) ) {
|
||||
// need to throttle slope, let's move the point
|
||||
// furthest away from average towards the center.
|
||||
|
||||
slope_error = true;
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " (a) detected slope of "
|
||||
<< slope << " dist = " << dist );
|
||||
|
||||
double e1 = fabs(average_elev_m - p1.z());
|
||||
double e2 = fabs(average_elev_m - p2.z());
|
||||
// cout << " z1 = " << p1.z() << " z2 = " << p2.z() << endl;
|
||||
// cout << " e1 = " << e1 << " e2 = " << e2 << endl;
|
||||
|
||||
if ( e1 > e2 ) {
|
||||
// cout << " p1 error larger" << endl;
|
||||
if ( slope > 0 ) {
|
||||
p1.setz( p2.z() - (dist * slope_max) );
|
||||
} else {
|
||||
p1.setz( p2.z() + (dist * slope_max) );
|
||||
}
|
||||
Pts->set(i1, j1, p1);
|
||||
} else {
|
||||
// cout << " p2 error larger" << endl;
|
||||
if ( slope > 0 ) {
|
||||
p2.setz( p1.z() + (dist * slope_max) );
|
||||
} else {
|
||||
p2.setz( p1.z() - (dist * slope_max) );
|
||||
}
|
||||
Pts->set(i2, j2, p2);
|
||||
}
|
||||
// cout << " z1 = " << p1.z() << " z2 = " << p2.z() << endl;
|
||||
}
|
||||
|
||||
return slope_error;
|
||||
}
|
||||
|
||||
|
||||
// Constructor, specify min and max coordinates of desired area in
|
||||
// lon/lat degrees
|
||||
TGAptSurface::TGAptSurface( const string& path,
|
||||
const string_list& elev_src,
|
||||
Point3D _min_deg, Point3D _max_deg,
|
||||
double _average_elev_m )
|
||||
{
|
||||
// Calculate desired size of grid
|
||||
min_deg = _min_deg;
|
||||
max_deg = _max_deg;
|
||||
average_elev_m = _average_elev_m;
|
||||
// cout << "min = " << min_deg << " max = " << max_deg
|
||||
// << " ave = " << average_elev_m << endl;
|
||||
|
||||
// The following size calculations are for the purpose of
|
||||
// determining grid divisions so it's not important that they be
|
||||
// *exact*, just ball park.
|
||||
double y_deg = max_deg.lat() - min_deg.lat();
|
||||
double y_rad = y_deg * SG_DEGREES_TO_RADIANS;
|
||||
double y_nm = y_rad * SG_RAD_TO_NM;
|
||||
double y_m = y_nm * SG_NM_TO_METER;
|
||||
|
||||
double xfact = cos( min_deg.lat() * SG_DEGREES_TO_RADIANS );
|
||||
double x_deg = max_deg.lon() - min_deg.lon();
|
||||
double x_rad = x_deg * SG_DEGREES_TO_RADIANS;
|
||||
double x_nm = x_rad * SG_RAD_TO_NM * xfact;
|
||||
double x_m = x_nm * SG_NM_TO_METER;
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG,
|
||||
"Area size = " << y_m << " x " << x_m << " (m)" );
|
||||
|
||||
int xdivs = (int)(x_m / coarse_grid) + 1;
|
||||
int ydivs = (int)(y_m / coarse_grid) + 1;
|
||||
|
||||
// set an arbitrary minumum number of divisions to keep things
|
||||
// interesting
|
||||
if ( xdivs < 8 ) { xdivs = 8; }
|
||||
if ( ydivs < 8 ) { ydivs = 8; }
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " M(" << ydivs << "," << xdivs << ")");
|
||||
|
||||
double dlon = x_deg / xdivs;
|
||||
double dlat = y_deg / ydivs;
|
||||
|
||||
double dlon_h = dlon * 0.5;
|
||||
double dlat_h = dlat * 0.5;
|
||||
|
||||
// Build the extra res input grid (shifted SW by half (dlon,dlat)
|
||||
// with an added major row column on the NE sides.)
|
||||
int mult = 10;
|
||||
SimpleMatrix dPts( (xdivs + 1) * mult + 1, (ydivs + 1) * mult + 1 );
|
||||
for ( int j = 0; j < dPts.rows(); ++j ) {
|
||||
for ( int i = 0; i < dPts.cols(); ++i ) {
|
||||
dPts.set(i, j, Point3D( min_deg.lon() - dlon_h
|
||||
+ i * (dlon / (double)mult),
|
||||
min_deg.lat() - dlat_h
|
||||
+ j * (dlat / (double)mult),
|
||||
-9999 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup the elevations of all the grid points
|
||||
tgCalcElevations( path, elev_src, dPts, 0.0 );
|
||||
#ifdef DEBUG
|
||||
for ( int j = 0; j < dPts.rows(); ++j ) {
|
||||
for ( int i = 0; i < dPts.cols(); ++i ) {
|
||||
printf("hr %.5f %.5f %.1f\n",
|
||||
dPts.element(i,j).x(), dPts.element(i,j).y(),
|
||||
dPts.element(i,j).z() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Clamp the elevations against the externally provided average
|
||||
// elevation.
|
||||
tgClampElevations( dPts, average_elev_m, max_clamp );
|
||||
|
||||
#ifdef DEBUG
|
||||
for ( int j = 0; j < dPts.rows(); ++j ) {
|
||||
for ( int i = 0; i < dPts.cols(); ++i ) {
|
||||
printf("chr %.5f %.5f %.1f\n",
|
||||
dPts.element(i,j).x(), dPts.element(i,j).y(),
|
||||
dPts.element(i,j).z() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Build the normal res input grid from the double res version
|
||||
Pts = new SimpleMatrix(xdivs + 1, ydivs + 1 );
|
||||
double ave_divider = (mult+1) * (mult+1);
|
||||
for ( int j = 0; j < Pts->rows(); ++j ) {
|
||||
for ( int i = 0; i < Pts->cols(); ++i ) {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, i << "," << j);
|
||||
double accum = 0.0;
|
||||
double lon_accum = 0.0;
|
||||
double lat_accum = 0.0;
|
||||
for ( int jj = 0; jj <= mult; ++jj ) {
|
||||
for ( int ii = 0; ii <= mult; ++ii ) {
|
||||
double value = dPts.element(mult*i + ii, mult*j + jj).z();
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "value = " << value );
|
||||
accum += value;
|
||||
lon_accum += dPts.element(mult*i + ii, mult*j + jj).x();
|
||||
lat_accum += dPts.element(mult*i + ii, mult*j + jj).y();
|
||||
}
|
||||
}
|
||||
double val_ave = accum / ave_divider;
|
||||
double lon_ave = lon_accum / ave_divider;
|
||||
double lat_ave = lat_accum / ave_divider;
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " val_ave = " << val_ave );
|
||||
Pts->set(i, j, Point3D( min_deg.lon() + i * dlon,
|
||||
min_deg.lat() + j * dlat,
|
||||
val_ave )
|
||||
);
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "lon_ave = " << lon_ave
|
||||
<< " lat_ave = " << lat_ave );
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "lon = " << min_deg.lon() + j * dlon
|
||||
<< " lat = " << min_deg.lat() + i * dlat );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for ( int j = 0; j < Pts->rows(); ++j ) {
|
||||
for ( int i = 0; i < Pts->cols(); ++i ) {
|
||||
printf("nr %.5f %.5f %.1f\n",
|
||||
Pts->element(i,j).x(),
|
||||
Pts->element(i,j).y(),
|
||||
Pts->element(i,j).z() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool slope_error = true;
|
||||
while ( slope_error ) {
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "start of slope processing pass" );
|
||||
slope_error = false;
|
||||
// Add some "slope" sanity to the resulting surface grid points
|
||||
for ( int j = 0; j < Pts->rows() - 1; ++j ) {
|
||||
for ( int i = 0; i < Pts->cols() - 1; ++i ) {
|
||||
if ( limit_slope( Pts, i, j, i+1, j, average_elev_m ) ) {
|
||||
slope_error = true;
|
||||
}
|
||||
if ( limit_slope( Pts, i, j, i, j+1, average_elev_m ) ) {
|
||||
slope_error = true;
|
||||
}
|
||||
if ( limit_slope( Pts, i, j, i+1, j+1, average_elev_m ) ) {
|
||||
slope_error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for ( int j = 0; j < Pts->rows(); ++j ) {
|
||||
for ( int i = 0; i < Pts->cols(); ++i ) {
|
||||
printf("%.5f %.5f %.1f\n",
|
||||
Pts->element(i,j).x(), Pts->element(i,j).y(),
|
||||
Pts->element(i,j).z() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// compute an central offset point.
|
||||
double clon = (min_deg.lon() + max_deg.lon()) / 2.0;
|
||||
double clat = (min_deg.lat() + max_deg.lat()) / 2.0;
|
||||
offset = Point3D( clon, clat, average_elev_m );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Central offset point = " << offset);
|
||||
|
||||
// Create the fitted surface
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "ready to create fitted surface");
|
||||
fit();
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " fit process successful.");
|
||||
|
||||
#ifdef DEBUG
|
||||
// For debugging only: output an array of surface points suitable
|
||||
// for plotting with gnuplot. This is useful for comparing the
|
||||
// approximated and smoothed surface to the original rough
|
||||
// surface.
|
||||
cout << "DEBUGGING TEST" << endl;
|
||||
const int divs = 100;
|
||||
double dx = x_deg / divs;
|
||||
double dy = y_deg / divs;
|
||||
for ( int j = 0; j < divs; ++j ) {
|
||||
for ( int i = 0; i < divs; ++i ) {
|
||||
double lon = min_deg.lon() + j * dx;
|
||||
double lat = min_deg.lat() + i * dy;
|
||||
printf("%.5f %.5f %.1f\n", lon, lat, query(lon, lat) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
TGAptSurface::~TGAptSurface() {
|
||||
delete Pts;
|
||||
}
|
||||
|
||||
|
||||
static ColumnVector qr_method( Real* y,
|
||||
Real* t1, Real* t2, Real* t3, Real* t4,
|
||||
Real* t5, Real* t6, Real* t7, Real* t8,
|
||||
Real* t9, Real* t10, Real* t11, Real* t12,
|
||||
Real* t13, Real* t14, Real* t15,
|
||||
int nobs, int npred )
|
||||
{
|
||||
cout << "QR triangularisation" << endl;;
|
||||
|
||||
// QR triangularisation method
|
||||
|
||||
// load data - 1s into col 1 of matrix
|
||||
int npred1 = npred+1;
|
||||
cout << "nobs = " << nobs << " npred1 = " << npred1 << endl;
|
||||
|
||||
Matrix X(nobs,npred1); ColumnVector Y(nobs);
|
||||
X.column(1) = 1.0;
|
||||
X.column(2) << t1;
|
||||
X.column(3) << t2;
|
||||
X.column(4) << t3;
|
||||
X.column(5) << t4;
|
||||
X.column(6) << t5;
|
||||
X.column(7) << t6;
|
||||
X.column(8) << t7;
|
||||
X.column(9) << t8;
|
||||
X.column(10) << t9;
|
||||
X.column(11) << t10;
|
||||
X.column(12) << t11;
|
||||
X.column(13) << t12;
|
||||
X.column(14) << t13;
|
||||
X.column(15) << t14;
|
||||
X.column(16) << t15;
|
||||
Y << y;
|
||||
|
||||
// do Householder triangularisation
|
||||
// no need to deal with constant term separately
|
||||
Matrix X1 = X; // Want copy of matrix
|
||||
ColumnVector Y1 = Y;
|
||||
UpperTriangularMatrix U; ColumnVector M;
|
||||
QRZ(X1, U); QRZ(X1, Y1, M); // Y1 now contains resids
|
||||
ColumnVector A = U.i() * M;
|
||||
ColumnVector Fitted = X * A;
|
||||
Real ResVar = sum_square(Y1) / (nobs-npred1);
|
||||
|
||||
// get variances of estimates
|
||||
U = U.i(); DiagonalMatrix D; D << U * U.t();
|
||||
|
||||
// Get diagonals of Hat matrix
|
||||
DiagonalMatrix Hat; Hat << X1 * X1.t();
|
||||
|
||||
cout << "A vector = " << A << endl;
|
||||
cout << "A rows = " << A.nrows() << endl;
|
||||
|
||||
// print out answers
|
||||
cout << "\nEstimates and their standard errors\n\n";
|
||||
ColumnVector SE(npred1);
|
||||
for (int i=1; i<=npred1; i++) SE(i) = sqrt(D(i)*ResVar);
|
||||
cout << setw(11) << setprecision(5) << (A | SE) << endl;
|
||||
cout << "\nObservations, fitted value, residual value, hat value\n";
|
||||
cout << setw(9) << setprecision(3) <<
|
||||
(X.columns(2,4) | Y | Fitted | Y1 | Hat.as_column());
|
||||
cout << "\n\n";
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
|
||||
// Use a linear least squares method to fit a 3d polynomial to the
|
||||
// sampled surface data
|
||||
void TGAptSurface::fit() {
|
||||
|
||||
// the fit function is:
|
||||
// f(x,y) = A1*x + A2*x*y + A3*y +
|
||||
// A4*x*x + A5+x*x*y + A6*x*x*y*y + A7*y*y + A8*x*y*y +
|
||||
// A9*x*x*x + A10*x*x*x*y + A11*x*x*x*y*y + A12*x*x*x*y*y*y +
|
||||
// A13*y*y*y + A14*x*y*y*y + A15*x*x*y*y*y
|
||||
|
||||
int nobs = Pts->cols() * Pts->rows(); // number of observations
|
||||
int npred = 15; // number of predictor values A[n]
|
||||
|
||||
vector<Real> tz(nobs);
|
||||
vector<Real> t1(nobs);
|
||||
vector<Real> t2(nobs);
|
||||
vector<Real> t3(nobs);
|
||||
vector<Real> t4(nobs);
|
||||
vector<Real> t5(nobs);
|
||||
vector<Real> t6(nobs);
|
||||
vector<Real> t7(nobs);
|
||||
vector<Real> t8(nobs);
|
||||
vector<Real> t9(nobs);
|
||||
vector<Real> t10(nobs);
|
||||
vector<Real> t11(nobs);
|
||||
vector<Real> t12(nobs);
|
||||
vector<Real> t13(nobs);
|
||||
vector<Real> t14(nobs);
|
||||
vector<Real> t15(nobs);
|
||||
|
||||
// generate the required fit data
|
||||
for ( int j = 0; j < Pts->rows(); j++ ) {
|
||||
for ( int i = 0; i < Pts->cols(); i++ ) {
|
||||
Point3D p = Pts->element( i, j );
|
||||
int index = ( j * Pts->cols() ) + i;
|
||||
Real x = p.x() - offset.x();
|
||||
Real y = p.y() - offset.y();
|
||||
Real z = p.z() - offset.z();
|
||||
//cout << "pt = " << x << "," << y << "," << z << endl;
|
||||
tz[index] = z;
|
||||
t1[index] = x;
|
||||
t2[index] = x*y;
|
||||
t3[index] = y;
|
||||
t4[index] = x*x;
|
||||
t5[index] = x*x*y;
|
||||
t6[index] = x*x*y*y;
|
||||
t7[index] = y*y;
|
||||
t8[index] = x*y*y;
|
||||
t9[index] = x*x*x;
|
||||
t10[index] = x*x*x*y;
|
||||
t11[index] = x*x*x*y*y;
|
||||
t12[index] = x*x*x*y*y*y;
|
||||
t13[index] = y*y*y;
|
||||
t14[index] = x*y*y*y;
|
||||
t15[index] = x*x*y*y*y;
|
||||
}
|
||||
}
|
||||
|
||||
// we want to find the values of a,b,c to give the best
|
||||
// fit
|
||||
|
||||
Try {
|
||||
surface_coefficients
|
||||
= qr_method( &tz[0],
|
||||
&t1[0], &t2[0], &t3[0], &t4[0], &t5[0], &t6[0], &t7[0], &t8[0],
|
||||
&t9[0], &t10[0], &t11[0], &t12[0], &t13[0], &t14[0], &t15[0],
|
||||
nobs, npred
|
||||
);
|
||||
cout << "surface_coefficients size = " << surface_coefficients.nrows() << endl;
|
||||
}
|
||||
CatchAll { cout << BaseException::what(); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Query the elevation of a point, return -9999 if out of range
|
||||
double TGAptSurface::query( double lon_deg, double lat_deg ) {
|
||||
// sanity check
|
||||
if ( lon_deg < min_deg.lon() || lon_deg > max_deg.lon() ||
|
||||
lat_deg < min_deg.lat() || lat_deg > max_deg.lat() )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_WARN,
|
||||
"Warning: query out of bounds for fitted surface!");
|
||||
return -9999.0;
|
||||
}
|
||||
|
||||
// compute the function with solved coefficients
|
||||
|
||||
// the fit function is:
|
||||
// f(x,y) = A1*x + A2*x*y + A3*y +
|
||||
// A4*x*x + A5+x*x*y + A6*x*x*y*y + A7*y*y + A8*x*y*y +
|
||||
// A9*x*x*x + A10*x*x*x*y + A11*x*x*x*y*y + A12*x*x*x*y*y*y +
|
||||
// A13*y*y*y + A14*x*y*y*y + A15*x*x*y*y*y
|
||||
|
||||
double x = lon_deg - offset.x();
|
||||
double y = lat_deg - offset.y();
|
||||
ColumnVector A = surface_coefficients;
|
||||
|
||||
double result = A(1) + A(2)*x + A(3)*x*y + A(4)*y + A(5)*x*x + A(6)*x*x*y
|
||||
+ A(7)*x*x*y*y + A(8)*y*y + A(9)*x*y*y + A(10)*x*x*x + A(11)*x*x*x*y
|
||||
+ A(12)*x*x*x*y*y + A(13)*x*x*x*y*y*y + A(14)*y*y*y + A(15)*x*y*y*y
|
||||
+ A(16)*x*x*y*y*y;
|
||||
result += offset.z();
|
||||
|
||||
printf("result = %.6f %.6f %.2f\n", lon_deg, lat_deg, result);
|
||||
|
||||
return result;
|
||||
}
|
148
src/Airports/GenAirports850/apt_surface.hxx
Normal file
148
src/Airports/GenAirports850/apt_surface.hxx
Normal file
|
@ -0,0 +1,148 @@
|
|||
// apt_surface.hxx -- class to manage airport terrain surface
|
||||
// approximation and smoothing
|
||||
//
|
||||
// Written by Curtis Olson, started March 2003.
|
||||
//
|
||||
// Copyright (C) 2003 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: apt_surface.hxx,v 1.9 2005-09-09 20:47:04 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _APT_SURFACE_HXX
|
||||
#define _APT_SURFACE_HXX
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
// libnewmat includes and defines
|
||||
#define WANT_STREAM // include.h will get stream fns
|
||||
#define WANT_MATH // include.h will get math fns
|
||||
// newmatap.h will get include.h
|
||||
#include <newmat/newmatap.h> // need matrix applications
|
||||
#include <newmat/newmatio.h> // need matrix output routines
|
||||
|
||||
#include <Geometry/point3d.hxx>
|
||||
|
||||
|
||||
/***
|
||||
* A dirt simple matrix class for our convenience based on top of Point3D
|
||||
*/
|
||||
|
||||
class SimpleMatrix {
|
||||
|
||||
private:
|
||||
|
||||
int _rows;
|
||||
int _cols;
|
||||
point_list m;
|
||||
|
||||
public:
|
||||
|
||||
inline SimpleMatrix( int columns, int rows ) {
|
||||
_cols = columns;
|
||||
_rows = rows;
|
||||
m.resize( _cols * _rows );
|
||||
}
|
||||
|
||||
inline Point3D element( int col, int row ) {
|
||||
int index = ( row * _cols ) + col;
|
||||
if ( col < 0 || col >= _cols ) {
|
||||
cout << "column out of bounds on read (" << col << " >= " << _cols << ")"
|
||||
<< endl;
|
||||
int *p = 0; *p = 1; // force crash
|
||||
} else if ( row < 0 || row >= _rows ) {
|
||||
cout << "row out of bounds on read (" << row << " >= " << _rows << ")"
|
||||
<< endl;
|
||||
int *p = 0; *p = 1; // force crash
|
||||
}
|
||||
return m[index];
|
||||
}
|
||||
|
||||
inline void set( int col, int row, Point3D p ) {
|
||||
int index = ( row * _cols ) + col;
|
||||
if ( col < 0 || col >= _cols ) {
|
||||
cout << "column out of bounds on set (" << col << " >= " << _cols << ")"
|
||||
<< endl;
|
||||
int *p = 0; *p = 1; // force crash
|
||||
} else if ( row < 0 || row >= _rows ) {
|
||||
cout << "row out of bounds on set (" << row << " >= " << _rows << ")"
|
||||
<< endl;
|
||||
int *p = 0; *p = 1; // force crash
|
||||
}
|
||||
m[index] = p;
|
||||
}
|
||||
|
||||
inline int cols() const { return _cols; }
|
||||
inline int rows() const { return _rows; }
|
||||
};
|
||||
|
||||
|
||||
/***
|
||||
* Note of explanation. When a TGAptSurface instance is created, you
|
||||
* must specify a min and max lon/lat containing the entire airport
|
||||
* area. The class will divide up that area into a reasonably sized
|
||||
* regular grid. It will then look up the elevation of each point on
|
||||
* the grid from the DEM/Array data. Finally it will fit do a linear
|
||||
* least squares polygonal surface approximation from this grid. Each
|
||||
* vertex of the actual airport model is drapped over this fitted
|
||||
* surface rather than over the underlying terrain data. This
|
||||
* provides a) smoothing of noisy terrain data and b) natural rises
|
||||
* and dips in the airport surface.
|
||||
*/
|
||||
|
||||
class TGAptSurface {
|
||||
|
||||
private:
|
||||
|
||||
// The actual nurbs surface approximation for the airport
|
||||
SimpleMatrix *Pts;
|
||||
ColumnVector surface_coefficients;
|
||||
|
||||
Point3D min_deg, max_deg;
|
||||
|
||||
// A central point in the airport area
|
||||
Point3D offset;
|
||||
|
||||
// externally seeded average airport elevation
|
||||
double average_elev_m;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructor, specify min and max coordinates of desired area in
|
||||
// lon/lat degrees, also please specify an "average" airport
|
||||
// elevations in meters.
|
||||
TGAptSurface( const string &path, const string_list& elev_src,
|
||||
Point3D _min_deg, Point3D _max_deg, double _average_elev_m );
|
||||
|
||||
// Destructor
|
||||
~TGAptSurface();
|
||||
|
||||
// Use a linear least squares method to fit a 3d polynomial to the
|
||||
// sampled surface data
|
||||
void fit();
|
||||
|
||||
// Query the elevation of a point, return -9999 if out of range.
|
||||
// This routine makes a simplistic assumption that X,Y space is
|
||||
// proportional to u,v space on the nurbs surface which it isn't.
|
||||
double query( double lon_deg, double lat_deg );
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _APT_SURFACE_HXX
|
1414
src/Airports/GenAirports850/build.cxx
Normal file
1414
src/Airports/GenAirports850/build.cxx
Normal file
File diff suppressed because it is too large
Load diff
49
src/Airports/GenAirports850/build.hxx
Normal file
49
src/Airports/GenAirports850/build.hxx
Normal file
|
@ -0,0 +1,49 @@
|
|||
// build.hxx -- routines to build polygon model of an airport from the runway
|
||||
// definition
|
||||
//
|
||||
// Written by Curtis Olson, started September 1999.
|
||||
//
|
||||
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: build.hxx,v 1.10 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _BUILD_HXX
|
||||
#define _BUILD_HXX
|
||||
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "global.hxx"
|
||||
#include "point2d.hxx"
|
||||
|
||||
|
||||
// build 3d airport
|
||||
void build_airport( string airport_id, float alt_m,
|
||||
string_list& runways_raw,
|
||||
string_list& beacons_raw,
|
||||
string_list& towers_raw,
|
||||
string_list& windsocks_raw,
|
||||
const string& root,
|
||||
const string_list& elev_src );
|
||||
|
||||
|
||||
|
||||
#endif // _BUILD_HXX
|
||||
|
||||
|
252
src/Airports/GenAirports850/convex_hull.cxx
Normal file
252
src/Airports/GenAirports850/convex_hull.cxx
Normal file
|
@ -0,0 +1,252 @@
|
|||
// convex_hull.cxx -- calculate the convex hull of a set of points
|
||||
//
|
||||
// Written by Curtis Olson, started September 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: convex_hull.cxx,v 1.12 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
|
||||
#include "convex_hull.hxx"
|
||||
#include "point2d.hxx"
|
||||
|
||||
using std::less;
|
||||
using std::map;
|
||||
|
||||
|
||||
// stl map typedefs
|
||||
typedef map < double, double, less<double> > map_container;
|
||||
typedef map_container::iterator map_iterator;
|
||||
|
||||
|
||||
// Calculate theta of angle (a, b, c)
|
||||
double calc_angle(Point3D a, Point3D b, Point3D c) {
|
||||
Point3D u, v;
|
||||
double udist, vdist, uv_dot, tmp;
|
||||
|
||||
// u . v = ||u|| * ||v|| * cos(theta)
|
||||
|
||||
u.setx( b.x() - a.x() );
|
||||
u.sety( b.y() - a.y() );
|
||||
udist = sqrt( u.x() * u.x() + u.y() * u.y() );
|
||||
// printf("udist = %.6f\n", udist);
|
||||
|
||||
v.setx( b.x() - c.x() );
|
||||
v.sety( b.y() - c.y() );
|
||||
vdist = sqrt( v.x() * v.x() + v.y() * v.y() );
|
||||
// printf("vdist = %.6f\n", vdist);
|
||||
|
||||
uv_dot = u.x() * v.x() + u.y() * v.y();
|
||||
// printf("uv_dot = %.6f\n", uv_dot);
|
||||
|
||||
tmp = uv_dot / (udist * vdist);
|
||||
// printf("tmp = %.6f\n", tmp);
|
||||
|
||||
return acos(tmp);
|
||||
}
|
||||
|
||||
|
||||
// Test to see if angle(Pa, Pb, Pc) < 180 degrees
|
||||
bool test_point(Point3D Pa, Point3D Pb, Point3D Pc) {
|
||||
double a1, a2;
|
||||
|
||||
Point3D origin( 0.0 );
|
||||
|
||||
Point3D a( cos(Pa.y()) * Pa.x(),
|
||||
sin(Pa.y()) * Pa.x(), 0 );
|
||||
|
||||
Point3D b( cos(Pb.y()) * Pb.x(),
|
||||
sin(Pb.y()) * Pb.x(), 0 );
|
||||
|
||||
Point3D c( cos(Pc.y()) * Pc.x(),
|
||||
sin(Pc.y()) * Pc.x(), 0 );
|
||||
|
||||
// printf("a is %.6f %.6f\n", a.x, a.y);
|
||||
// printf("b is %.6f %.6f\n", b.x, b.y);
|
||||
// printf("c is %.6f %.6f\n", c.x, c.y);
|
||||
|
||||
a1 = calc_angle(a, b, origin);
|
||||
a2 = calc_angle(origin, b, c);
|
||||
|
||||
// printf("a1 = %.2f a2 = %.2f\n", a1 * SGD_RADIANS_TO_DEGREES, a2 * SGD_RADIANS_TO_DEGREES);
|
||||
|
||||
return ( (a1 + a2) < SGD_PI );
|
||||
}
|
||||
|
||||
|
||||
// calculate the convex hull of a set of points, return as a list of
|
||||
// point2d. The algorithm description can be found at:
|
||||
// http://riot.ieor.berkeley.edu/riot/Applications/ConvexHull/CHDetails.html
|
||||
TGPolygon convex_hull( const point_list& input_list ) {
|
||||
int i;
|
||||
|
||||
map_iterator map_current, map_next, map_next_next, map_last;
|
||||
|
||||
// list of translated points
|
||||
point_list trans_list;
|
||||
|
||||
// points sorted by radian degrees
|
||||
map_container radians_map;
|
||||
|
||||
// will contain the convex hull
|
||||
TGPolygon con_hull;
|
||||
|
||||
Point3D p, Pa, Pb, Pc, result;
|
||||
double sum_x, sum_y;
|
||||
int in_count, last_size;
|
||||
|
||||
// STEP ONE: Find an average midpoint of the input set of points
|
||||
in_count = input_list.size();
|
||||
sum_x = sum_y = 0.0;
|
||||
|
||||
for ( i = 0; i < in_count; ++i ) {
|
||||
sum_x += input_list[i].x();
|
||||
sum_y += input_list[i].y();
|
||||
}
|
||||
|
||||
Point3D average( sum_x / in_count, sum_y / in_count, 0 );
|
||||
|
||||
// printf("Average center point is %.4f %.4f\n", average.x, average.y);
|
||||
|
||||
// STEP TWO: Translate input points so average is at origin
|
||||
trans_list.clear();
|
||||
|
||||
for ( i = 0; i < in_count; ++i ) {
|
||||
p = Point3D( input_list[i].x() - average.x(),
|
||||
input_list[i].y() - average.y(), 0 );
|
||||
// printf("%.6f %.6f\n", p.x, p.y);
|
||||
trans_list.push_back( p );
|
||||
}
|
||||
|
||||
// STEP THREE: convert to radians and sort by theta
|
||||
radians_map.clear();
|
||||
|
||||
for ( i = 0; i < in_count; ++i ) {
|
||||
p = cart_to_polar_2d( trans_list[i] );
|
||||
if ( p.x() > radians_map[p.y()] ) {
|
||||
radians_map[p.y()] = p.x();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// printf("Sorted list\n");
|
||||
map_current = radians_map.begin();
|
||||
map_last = radians_map.end();
|
||||
for ( ; map_current != map_last ; ++map_current ) {
|
||||
p.setx( (*map_current).first );
|
||||
p.sety( (*map_current).second );
|
||||
|
||||
printf("p is %.6f %.6f\n", p.x(), p.y());
|
||||
}
|
||||
*/
|
||||
|
||||
// STEP FOUR: traverse the sorted list and eliminate everything
|
||||
// not on the perimeter.
|
||||
// printf("Traversing list\n");
|
||||
|
||||
// double check list size ... this should never fail because a
|
||||
// single runway will always generate four points.
|
||||
if ( radians_map.size() < 3 ) {
|
||||
throw sg_exception("convex hull not possible with < 3 points");
|
||||
}
|
||||
|
||||
// ensure that we run the while loop at least once
|
||||
last_size = radians_map.size() + 1;
|
||||
|
||||
while ( last_size > (int)radians_map.size() ) {
|
||||
// printf("Running an iteration of the graham scan algorithm\n");
|
||||
last_size = radians_map.size();
|
||||
|
||||
map_current = radians_map.begin();
|
||||
while ( map_current != radians_map.end() ) {
|
||||
// get first element
|
||||
Pa.sety( (*map_current).first );
|
||||
Pa.setx( (*map_current).second );
|
||||
|
||||
// get second element
|
||||
map_next = map_current;
|
||||
++map_next;
|
||||
if ( map_next == radians_map.end() ) {
|
||||
map_next = radians_map.begin();
|
||||
}
|
||||
Pb.sety( (*map_next).first );
|
||||
Pb.setx( (*map_next).second );
|
||||
|
||||
// get third element
|
||||
map_next_next = map_next;
|
||||
++map_next_next;
|
||||
if ( map_next_next == radians_map.end() ) {
|
||||
map_next_next = radians_map.begin();
|
||||
}
|
||||
Pc.sety( (*map_next_next).first );
|
||||
Pc.setx( (*map_next_next).second );
|
||||
|
||||
// printf("Pa is %.6f %.6f\n", Pa.y(), Pa.x());
|
||||
// printf("Pb is %.6f %.6f\n", Pb.y(), Pb.x());
|
||||
// printf("Pc is %.6f %.6f\n", Pc.y(), Pc.x());
|
||||
|
||||
if ( test_point(Pa, Pb, Pc) ) {
|
||||
// printf("Accepted a point\n");
|
||||
// accept point, advance Pa, Pb, and Pc.
|
||||
++map_current;
|
||||
} else {
|
||||
// printf("REJECTED A POINT\n");
|
||||
// reject point, delete it and advance only Pb and Pc
|
||||
map_next = map_current;
|
||||
++map_next;
|
||||
if ( map_next == radians_map.end() ) {
|
||||
map_next = radians_map.begin();
|
||||
}
|
||||
radians_map.erase( map_next );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// translate back to correct lon/lat
|
||||
// printf("Final sorted convex hull\n");
|
||||
con_hull.erase();
|
||||
map_current = radians_map.begin();
|
||||
map_last = radians_map.end();
|
||||
for ( ; map_current != map_last ; ++map_current ) {
|
||||
p.sety( (*map_current).first );
|
||||
p.setx( (*map_current).second );
|
||||
|
||||
result.setx( cos(p.y()) * p.x() + average.x() );
|
||||
result.sety( sin(p.y()) * p.x() + average.y() );
|
||||
|
||||
// printf("%.6f %.6f\n", result.x, result.y);
|
||||
|
||||
con_hull.add_node(0, result);
|
||||
}
|
||||
|
||||
return con_hull;
|
||||
}
|
47
src/Airports/GenAirports850/convex_hull.hxx
Normal file
47
src/Airports/GenAirports850/convex_hull.hxx
Normal file
|
@ -0,0 +1,47 @@
|
|||
// convex_hull.hxx -- calculate the convex hull of a set of points
|
||||
//
|
||||
// Written by Curtis Olson, started September 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: convex_hull.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _CONVEX_HULL_HXX
|
||||
#define _CONVEX_HULL_HXX
|
||||
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
|
||||
#include "point2d.hxx"
|
||||
|
||||
|
||||
|
||||
// calculate the convex hull of a set of points, return as a list of
|
||||
// point2d. The algorithm description can be found at:
|
||||
// http://riot.ieor.berkeley.edu/riot/Applications/ConvexHull/CHDetails.html
|
||||
TGPolygon convex_hull( const point_list& input_list );
|
||||
|
||||
|
||||
#endif // _CONVEX_HULL_HXX
|
||||
|
||||
|
282
src/Airports/GenAirports850/elevations.cxx
Normal file
282
src/Airports/GenAirports850/elevations.cxx
Normal file
|
@ -0,0 +1,282 @@
|
|||
// elevations.cxx -- routines to help calculate DEM elevations for a
|
||||
// set of points
|
||||
//
|
||||
// Written by Curtis Olson, started April 2004.
|
||||
//
|
||||
// Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: elevations.cxx,v 1.8 2005-12-19 16:51:25 curt Exp $
|
||||
//
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
// libnewmat includes and defines
|
||||
#define WANT_STREAM // include.h will get stream fns
|
||||
#define WANT_MATH // include.h will get math fns
|
||||
// newmatap.h will get include.h
|
||||
#include <newmat/newmatap.h> // need matrix applications
|
||||
#include <newmat/newmatio.h> // need matrix output routines
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include <Array/array.hxx>
|
||||
|
||||
#include "global.hxx"
|
||||
#include "apt_surface.hxx"
|
||||
|
||||
|
||||
// lookup node elevations for each point in the point_list. Returns
|
||||
// average of all points. Doesn't modify the original list.
|
||||
|
||||
double tgAverageElevation( const string &root, const string_list elev_src,
|
||||
const point_list points_source )
|
||||
{
|
||||
bool done = false;
|
||||
unsigned int i;
|
||||
TGArray array;
|
||||
|
||||
// make a copy so our routine is non-destructive.
|
||||
point_list points = points_source;
|
||||
|
||||
// just bail if no work to do
|
||||
if ( points.size() == 0 ) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// set all elevations to -9999
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
points[i].setz( -9999.0 );
|
||||
}
|
||||
|
||||
while ( !done ) {
|
||||
// find first node with -9999 elevation
|
||||
Point3D first(0.0);
|
||||
bool found_one = false;
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
if ( points[i].z() < -9000.0 && !found_one ) {
|
||||
first = points[i];
|
||||
found_one = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( found_one ) {
|
||||
SGBucket b( first.x(), first.y() );
|
||||
string base = b.gen_base_path();
|
||||
|
||||
// try the various elevation sources
|
||||
i = 0;
|
||||
bool found_file = false;
|
||||
while ( !found_file && i < elev_src.size() ) {
|
||||
string array_path = root + "/" + elev_src[i] + "/" + base
|
||||
+ "/" + b.gen_index_str();
|
||||
if ( array.open(array_path) ) {
|
||||
found_file = true;
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "Using array_path = "
|
||||
<< array_path );
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// this will fill in a zero structure if no array data
|
||||
// found/opened
|
||||
array.parse( b );
|
||||
|
||||
// this will do a hasty job of removing voids by inserting
|
||||
// data from the nearest neighbor (sort of)
|
||||
array.remove_voids();
|
||||
|
||||
// update all the non-updated elevations that are inside
|
||||
// this array file
|
||||
double elev;
|
||||
done = true;
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
if ( points[i].z() < -9000.0 ) {
|
||||
done = false;
|
||||
elev = array.altitude_from_grid( points[i].lon() * 3600.0,
|
||||
points[i].lat() * 3600.0 );
|
||||
if ( elev > -9000 ) {
|
||||
points[i].setz( elev );
|
||||
// cout << "interpolating for " << p << endl;
|
||||
// cout << p.x() << " " << p.y() << " " << p.z()
|
||||
// << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array.close();
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
// now find the average height of the queried points
|
||||
double total = 0.0;
|
||||
int count = 0;
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
total += points[i].z();
|
||||
count++;
|
||||
}
|
||||
double average = total / (double) count;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Average surface height of point list = "
|
||||
<< average);
|
||||
|
||||
return average;
|
||||
}
|
||||
|
||||
|
||||
// lookup node elevations for each point in the specified simple
|
||||
// matrix. Returns average of all points.
|
||||
|
||||
void tgCalcElevations( const string &root, const string_list elev_src,
|
||||
SimpleMatrix &Pts, const double average )
|
||||
{
|
||||
bool done = false;
|
||||
int i, j;
|
||||
TGArray array;
|
||||
|
||||
// just bail if no work to do
|
||||
if ( Pts.rows() == 0 || Pts.cols() == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set all elevations to -9999
|
||||
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||
Point3D p = Pts.element(i, j);
|
||||
p.setz( -9999.0 );
|
||||
Pts.set(i, j, p);
|
||||
}
|
||||
}
|
||||
|
||||
while ( !done ) {
|
||||
// find first node with -9999 elevation
|
||||
Point3D first(0.0);
|
||||
bool found_one = false;
|
||||
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||
Point3D p = Pts.element(i,j);
|
||||
if ( p.z() < -9000.0 && !found_one ) {
|
||||
first = p;
|
||||
found_one = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( found_one ) {
|
||||
SGBucket b( first.x(), first.y() );
|
||||
string base = b.gen_base_path();
|
||||
|
||||
// try the various elevation sources
|
||||
j = 0;
|
||||
bool found_file = false;
|
||||
while ( !found_file && j < (int)elev_src.size() ) {
|
||||
string array_path = root + "/" + elev_src[j] + "/" + base
|
||||
+ "/" + b.gen_index_str();
|
||||
if ( array.open(array_path) ) {
|
||||
found_file = true;
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "Using array_path = "
|
||||
<< array_path );
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
// this will fill in a zero structure if no array data
|
||||
// found/opened
|
||||
array.parse( b );
|
||||
|
||||
// this will do a hasty job of removing voids by inserting
|
||||
// data from the nearest neighbor (sort of)
|
||||
array.remove_voids();
|
||||
|
||||
// update all the non-updated elevations that are inside
|
||||
// this array file
|
||||
double elev;
|
||||
done = true;
|
||||
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||
Point3D p = Pts.element(i,j);
|
||||
if ( p.z() < -9000.0 ) {
|
||||
done = false;
|
||||
elev = array.altitude_from_grid( p.x() * 3600.0,
|
||||
p.y() * 3600.0 );
|
||||
if ( elev > -9000 ) {
|
||||
p.setz( elev );
|
||||
Pts.set(i, j, p);
|
||||
// cout << "interpolating for " << p << endl;
|
||||
// cout << p.x() << " " << p.y() << " " << p.z()
|
||||
// << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array.close();
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
// do some post processing for sanity's sake
|
||||
|
||||
// find the average height of the queried points
|
||||
double total = 0.0;
|
||||
int count = 0;
|
||||
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||
Point3D p = Pts.element(i,j);
|
||||
total += p.z();
|
||||
count++;
|
||||
}
|
||||
}
|
||||
double grid_average = total / (double) count;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Average surface height of matrix = "
|
||||
<< grid_average);
|
||||
}
|
||||
|
||||
|
||||
// clamp all elevations to the specified range
|
||||
|
||||
void tgClampElevations( SimpleMatrix &Pts,
|
||||
double center_m, double max_clamp_m )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
// go through the elevations and clamp all elevations to within
|
||||
// +/-max_m of the center_m elevation.
|
||||
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||
Point3D p = Pts.element(i,j);
|
||||
if ( p.z() < center_m - max_clamp_m ) {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " clamping " << p.z()
|
||||
<< " to " << center_m - max_clamp_m );
|
||||
p.setz( center_m - max_clamp_m );
|
||||
Pts.set(i, j, p);
|
||||
}
|
||||
if ( p.z() > center_m + max_clamp_m ) {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " clamping " << p.z()
|
||||
<< " to " << center_m + max_clamp_m );
|
||||
p.setz( center_m + max_clamp_m );
|
||||
Pts.set(i, j, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
src/Airports/GenAirports850/elevations.hxx
Normal file
56
src/Airports/GenAirports850/elevations.hxx
Normal file
|
@ -0,0 +1,56 @@
|
|||
// elevations.hxx -- routines to help calculate DEM elevations for a
|
||||
// set of points
|
||||
//
|
||||
// Written by Curtis Olson, started April 2004.
|
||||
//
|
||||
// Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: elevations.hxx,v 1.4 2005-09-09 15:05:15 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
// libnewmat includes and defines
|
||||
#define WANT_STREAM // include.h will get stream fns
|
||||
#define WANT_MATH // include.h will get math fns
|
||||
// newmatap.h will get include.h
|
||||
#include <newmat/newmatap.h> // need matrix applications
|
||||
#include <newmat/newmatio.h> // need matrix output routines
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include <Array/array.hxx>
|
||||
|
||||
#include "global.hxx"
|
||||
#include "apt_surface.hxx"
|
||||
|
||||
|
||||
// lookup node elevations for each point in the point_list. Returns
|
||||
// average of all points. Doesn't modify the original list.
|
||||
double tgAverageElevation( const string &root, const string_list elev_src,
|
||||
const point_list points_source );
|
||||
|
||||
// lookup node elevations for each point in the specified nurbs++
|
||||
// matrix.
|
||||
void tgCalcElevations( const string &root, const string_list elev_src,
|
||||
SimpleMatrix &Pts, double average );
|
||||
|
||||
// clamp all elevations to the specified range
|
||||
void tgClampElevations( SimpleMatrix &Pts,
|
||||
double center_m, double max_clamp_m );
|
45
src/Airports/GenAirports850/global.hxx
Normal file
45
src/Airports/GenAirports850/global.hxx
Normal file
|
@ -0,0 +1,45 @@
|
|||
// global.hxx -- kind of dumb but oh well...
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: global.hxx,v 1.9 2005-10-31 18:43:27 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _GEN_AIRPORT_GLOBAL_HXX
|
||||
#define _GEN_AIRPORT_GLOBAL_HXX
|
||||
|
||||
|
||||
extern int nudge;
|
||||
|
||||
// Final grid size for airport surface (in meters)
|
||||
const double coarse_grid = 300.0;
|
||||
|
||||
// compared to the average surface elevation, clamp all values within
|
||||
// this many meters of the average
|
||||
const double max_clamp = 100.0;
|
||||
|
||||
// maximum slope (rise/run) allowed on an airport surface
|
||||
extern double slope_max; // = 0.02;
|
||||
const double slope_eps = 0.00001;
|
||||
|
||||
// nurbs query/search epsilon
|
||||
const double nurbs_eps = 0.0000001;
|
||||
|
||||
#endif // _GEN_AIRPORT_GLOBAL_HXX
|
2973
src/Airports/GenAirports850/lights.cxx
Normal file
2973
src/Airports/GenAirports850/lights.cxx
Normal file
File diff suppressed because it is too large
Load diff
44
src/Airports/GenAirports850/lights.hxx
Normal file
44
src/Airports/GenAirports850/lights.hxx
Normal file
|
@ -0,0 +1,44 @@
|
|||
// lights.hxx -- Generate runway lighting
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: lights.hxx,v 1.8 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _RWY_LIGHTS_HXX
|
||||
#define _RWY_LIGHTS_HXX
|
||||
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "texparams.hxx"
|
||||
|
||||
|
||||
// generate runway lighting
|
||||
void gen_runway_lights( const TGRunway& rwy_info, float alt_m,
|
||||
superpoly_list &lights, TGPolygon *apt_base );
|
||||
|
||||
// generate taxiway lighting
|
||||
void gen_taxiway_lights( const TGRunway& taxiway_info, float alt_m,
|
||||
superpoly_list &lights );
|
||||
|
||||
#endif // _RWY_LIGHTS_HXX
|
491
src/Airports/GenAirports850/main.cxx
Normal file
491
src/Airports/GenAirports850/main.cxx
Normal file
|
@ -0,0 +1,491 @@
|
|||
// main.cxx -- main loop
|
||||
//
|
||||
// Written by Curtis Olson, started March 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: main.cxx,v 1.37 2005/12/19 15:53:21 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/misc/sgstream.hxx>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
|
||||
#include <Polygon/index.hxx>
|
||||
#include <Geometry/util.hxx>
|
||||
|
||||
#include "build.hxx"
|
||||
#include "convex_hull.hxx"
|
||||
|
||||
using std::vector;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
||||
int nudge = 10;
|
||||
double slope_max = 0.2;
|
||||
|
||||
static int is_in_range( string_list & runway_list, float min_lat, float max_lat, float min_lon, float max_lon );
|
||||
|
||||
// Display usage
|
||||
static void usage( int argc, char **argv ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"Usage " << argv[0] << " --input=<apt_file> "
|
||||
<< "--work=<work_dir> [ --start-id=abcd ] [ --nudge=n ] "
|
||||
<< "[--min-lon=<deg>] [--max-lon=<deg>] [--min-lat=<deg>] [--max-lat=<deg>] "
|
||||
<< "[--clear-dem-path] [--dem-path=<path>] [--max-slope=<decimal>] "
|
||||
<< "[ --airport=abcd ] [--tile=<tile>] [--chunk=<chunk>] [--verbose] [--help]");
|
||||
}
|
||||
|
||||
void setup_default_elevation_sources(string_list& elev_src) {
|
||||
elev_src.push_back( "SRTM2-Africa-3" );
|
||||
elev_src.push_back( "SRTM2-Australia-3" );
|
||||
elev_src.push_back( "SRTM2-Eurasia-3" );
|
||||
elev_src.push_back( "SRTM2-Islands-3" );
|
||||
elev_src.push_back( "SRTM2-North_America-3" );
|
||||
elev_src.push_back( "SRTM2-South_America-3" );
|
||||
elev_src.push_back( "DEM-USGS-3" );
|
||||
elev_src.push_back( "SRTM-1" );
|
||||
elev_src.push_back( "SRTM-3" );
|
||||
elev_src.push_back( "SRTM-30" );
|
||||
}
|
||||
|
||||
// Display help and usage
|
||||
static void help( int argc, char **argv, const string_list& elev_src ) {
|
||||
cout << "genapts generates airports for use in generating scenery for the FlightGear flight simulator. ";
|
||||
cout << "Airport, runway, and taxiway vector data and attributes are input, and generated 3D airports ";
|
||||
cout << "are output for further processing by the TerraGear scenery creation tools. ";
|
||||
cout << "\n\n";
|
||||
cout << "The standard input file is runways.dat.gz which is found in $FG_ROOT/Airports. ";
|
||||
cout << "This file is periodically generated for the FlightGear project by Robin Peel, who ";
|
||||
cout << "maintains an airport database for both the X-Plane and FlightGear simulators. ";
|
||||
cout << "The format of this file is documented on the FlightGear web site. ";
|
||||
cout << "Any other input file corresponding to this format may be used as input to genapts. ";
|
||||
cout << "Input files may be gzipped or left as plain text as required. ";
|
||||
cout << "\n\n";
|
||||
cout << "Processing all the world's airports takes a *long* time. To cut down processing time ";
|
||||
cout << "when only some airports are required, you may refine the input selection either by airport ";
|
||||
cout << "or by area. By airport, either one airport can be specified using --airport=abcd, where abcd is ";
|
||||
cout << "a valid airport code eg. --airport-id=KORD, or a starting airport can be specified using --start-id=abcd ";
|
||||
cout << "where once again abcd is a valid airport code. In this case, all airports in the file subsequent to the ";
|
||||
cout << "start-id are done. This is convienient when re-starting after a previous error. ";
|
||||
cout << "\nAn input area may be specified by lat and lon extent using min and max lat and lon. ";
|
||||
cout << "Alternatively, you may specify a chunk (10 x 10 degrees) or tile (1 x 1 degree) using a string ";
|
||||
cout << "such as eg. w080n40, e000s27. ";
|
||||
cout << "\nAn input file containing only a subset of the world's ";
|
||||
cout << "airports may of course be used.";
|
||||
cout << "\n\n";
|
||||
cout << "It is necessary to generate the elevation data for the area of interest PRIOR TO GENERATING THE AIRPORTS. ";
|
||||
cout << "Failure to do this will result in airports being generated with an elevation of zero. ";
|
||||
cout << "The following subdirectories of the work-dir will be searched for elevation files:\n\n";
|
||||
|
||||
string_list::const_iterator elev_src_it;
|
||||
for (elev_src_it = elev_src.begin(); elev_src_it != elev_src.end(); elev_src_it++) {
|
||||
cout << *elev_src_it << "\n";
|
||||
}
|
||||
cout << "\n";
|
||||
usage( argc, argv );
|
||||
}
|
||||
|
||||
|
||||
// reads the apt_full file and extracts and processes the individual
|
||||
// airport records
|
||||
int main( int argc, char **argv ) {
|
||||
float min_lon = -180;
|
||||
float max_lon = 180;
|
||||
float min_lat = -90;
|
||||
float max_lat = 90;
|
||||
bool ready_to_go = true;
|
||||
|
||||
string_list elev_src;
|
||||
elev_src.clear();
|
||||
setup_default_elevation_sources(elev_src);
|
||||
|
||||
sglog().setLogLevels( SG_GENERAL, SG_INFO );
|
||||
|
||||
// parse arguments
|
||||
string work_dir = "";
|
||||
string input_file = "";
|
||||
string start_id = "";
|
||||
string airport_id = "";
|
||||
int arg_pos;
|
||||
for (arg_pos = 1; arg_pos < argc; arg_pos++) {
|
||||
string arg = argv[arg_pos];
|
||||
if ( arg.find("--work=") == 0 ) {
|
||||
work_dir = arg.substr(7);
|
||||
} else if ( arg.find("--input=") == 0 ) {
|
||||
input_file = arg.substr(8);
|
||||
} else if ( arg.find("--terrain=") == 0 ) {
|
||||
elev_src.push_back( arg.substr(10) );
|
||||
} else if ( arg.find("--start-id=") == 0 ) {
|
||||
start_id = arg.substr(11);
|
||||
ready_to_go = false;
|
||||
} else if ( arg.find("--nudge=") == 0 ) {
|
||||
nudge = atoi( arg.substr(8).c_str() );
|
||||
} else if ( arg.find("--min-lon=") == 0 ) {
|
||||
min_lon = atof( arg.substr(10).c_str() );
|
||||
} else if ( arg.find("--max-lon=") == 0 ) {
|
||||
max_lon = atof( arg.substr(10).c_str() );
|
||||
} else if ( arg.find("--min-lat=") == 0 ) {
|
||||
min_lat = atof( arg.substr(10).c_str() );
|
||||
} else if ( arg.find("--max-lat=") == 0 ) {
|
||||
max_lat = atof( arg.substr(10).c_str() );
|
||||
} else if ( arg.find("--chunk=") == 0 ) {
|
||||
tg::Rectangle rectangle = tg::parseChunk(arg.substr(8).c_str(),
|
||||
10.0);
|
||||
min_lon = rectangle.getMin().x();
|
||||
min_lat = rectangle.getMin().y();
|
||||
max_lon = rectangle.getMax().x();
|
||||
max_lat = rectangle.getMax().y();
|
||||
} else if ( arg.find("--tile=") == 0 ) {
|
||||
tg::Rectangle rectangle = tg::parseTile(arg.substr(7).c_str());
|
||||
min_lon = rectangle.getMin().x();
|
||||
min_lat = rectangle.getMin().y();
|
||||
max_lon = rectangle.getMax().x();
|
||||
max_lat = rectangle.getMax().y();
|
||||
} else if ( arg.find("--airport=") == 0 ) {
|
||||
airport_id = arg.substr(10).c_str();
|
||||
ready_to_go = false;
|
||||
} else if ( arg == "--clear-dem-path" ) {
|
||||
elev_src.clear();
|
||||
} else if ( arg.find("--dem-path=") == 0 ) {
|
||||
elev_src.push_back( arg.substr(11) );
|
||||
} else if ( (arg.find("--verbose") == 0) || (arg.find("-v") == 0) ) {
|
||||
sglog().setLogLevels( SG_GENERAL, SG_BULK );
|
||||
} else if ( (arg.find("--max-slope=") == 0) ) {
|
||||
slope_max = atof( arg.substr(12).c_str() );
|
||||
} else if ( (arg.find("--help") == 0) || (arg.find("-h") == 0) ) {
|
||||
help( argc, argv, elev_src );
|
||||
exit(-1);
|
||||
} else {
|
||||
usage( argc, argv );
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Input file = " << input_file);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Terrain sources = ");
|
||||
for ( unsigned int i = 0; i < elev_src.size(); ++i ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " " << work_dir << "/" << elev_src[i] );
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Work directory = " << work_dir);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Nudge = " << nudge);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Longitude = " << min_lon << ':' << max_lon);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Latitude = " << min_lat << ':' << max_lat);
|
||||
|
||||
if (max_lon < min_lon || max_lat < min_lat ||
|
||||
min_lat < -90 || max_lat > 90 ||
|
||||
min_lon < -180 || max_lon > 180) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Bad longitude or latitude");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( work_dir == "" ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Error: no work directory specified." );
|
||||
usage( argc, argv );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ( input_file == "" ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Error: no input file." );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// make work directory
|
||||
string airportareadir=work_dir+"/AirportArea";
|
||||
SGPath sgp( airportareadir );
|
||||
sgp.append( "dummy" );
|
||||
sgp.create_dir( 0755 );
|
||||
|
||||
string lastaptfile = work_dir+"/last_apt";
|
||||
|
||||
// initialize persistant polygon counter
|
||||
string counter_file = airportareadir+"/poly_counter";
|
||||
poly_index_init( counter_file );
|
||||
|
||||
sg_gzifstream in( input_file );
|
||||
if ( !in.is_open() ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << input_file );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
string_list runways_list;
|
||||
string_list beacon_list;
|
||||
string_list tower_list;
|
||||
string_list windsock_list;
|
||||
|
||||
vector<string> token;
|
||||
string last_apt_id = "";
|
||||
string last_apt_info = "";
|
||||
string last_apt_type = "";
|
||||
string line;
|
||||
char tmp[2048];
|
||||
|
||||
while ( ! in.eof() ) {
|
||||
in.getline(tmp, 2048);
|
||||
line = tmp;
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "-> '" << line << "'" );
|
||||
if ( line.length() ) {
|
||||
token = simgear::strutils::split( line );
|
||||
if ( token.size() ) {
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "token[0] " << token[0] );
|
||||
}
|
||||
} else {
|
||||
token.clear();
|
||||
}
|
||||
|
||||
if ( !line.length() || !token.size() ) {
|
||||
// empty line, skip
|
||||
} else if ( (token[0] == "#") || (token[0] == "//") ) {
|
||||
// comment, skip
|
||||
} else if ( token[0] == "I" ) {
|
||||
// First line, indicates IBM (i.e. DOS line endings I
|
||||
// believe.)
|
||||
|
||||
// move past this line and read and discard the next line
|
||||
// which is the version and copyright information
|
||||
in.getline(tmp, 2048);
|
||||
vector<string> vers_token = simgear::strutils::split( tmp );
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Data version = " << vers_token[0] );
|
||||
} else if ( token[0] == "1" /* Airport */ ||
|
||||
token[0] == "16" /* Seaplane base */ ||
|
||||
token[0] == "17" /* Heliport */ ) {
|
||||
|
||||
// extract some airport runway info
|
||||
string rwy;
|
||||
float lat, lon;
|
||||
|
||||
string id = token[4];
|
||||
int elev = atoi( token[1].c_str() );
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Next airport = " << id << " " << elev );
|
||||
|
||||
if ( !last_apt_id.empty()) {
|
||||
if ( runways_list.size() ) {
|
||||
vector<string> rwy_token
|
||||
= simgear::strutils::split( runways_list[0] );
|
||||
rwy = token[8];
|
||||
lat = atof( token[9].c_str() );
|
||||
lon = atof( token[10].c_str() );
|
||||
|
||||
if ( airport_id.length() && airport_id == last_apt_id ) {
|
||||
ready_to_go = true;
|
||||
} else if ( start_id.length() && start_id == last_apt_id ) {
|
||||
ready_to_go = true;
|
||||
}
|
||||
|
||||
if ( ready_to_go ) {
|
||||
// check point our location
|
||||
char command[256];
|
||||
sprintf( command,
|
||||
"echo before building %s >> %s",
|
||||
last_apt_id.c_str(),
|
||||
lastaptfile.c_str() );
|
||||
system( command );
|
||||
|
||||
// process previous record
|
||||
// process_airport(last_apt_id, runways_list, argv[2]);
|
||||
try {
|
||||
if ( last_apt_type == "16" /* Seaplane base */ ||
|
||||
last_apt_type == "17" /* Heliport */ ) {
|
||||
// skip building heliports and
|
||||
// seaplane bases
|
||||
} else {
|
||||
if( is_in_range( runways_list, min_lat, max_lat, min_lon, max_lon ) ) {
|
||||
build_airport( last_apt_id,
|
||||
elev * SG_FEET_TO_METER,
|
||||
runways_list,
|
||||
beacon_list,
|
||||
tower_list,
|
||||
windsock_list,
|
||||
work_dir, elev_src );
|
||||
}
|
||||
}
|
||||
} catch (sg_exception &e) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Failed to build airport = "
|
||||
<< last_apt_id );
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Exception: "
|
||||
<< e.getMessage() );
|
||||
exit(-1);
|
||||
}
|
||||
if ( airport_id.length() ) {
|
||||
ready_to_go = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!airport_id.length()) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO,
|
||||
"ERRO: No runways, skipping = " << id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_apt_id = id;
|
||||
last_apt_info = line;
|
||||
last_apt_type = token[0];
|
||||
|
||||
// clear runway list for start of next airport
|
||||
runways_list.clear();
|
||||
beacon_list.clear();
|
||||
tower_list.clear();
|
||||
windsock_list.clear();
|
||||
} else if ( token[0] == "100" ) {
|
||||
// runway entry
|
||||
runways_list.push_back(line);
|
||||
} else if ( token[0] == "18" ) {
|
||||
// beacon entry
|
||||
beacon_list.push_back(line);
|
||||
} else if ( token[0] == "14" ) {
|
||||
// control tower entry
|
||||
tower_list.push_back(line);
|
||||
} else if ( token[0] == "19" ) {
|
||||
// windsock entry
|
||||
windsock_list.push_back(line);
|
||||
} else if ( token[0] == "21" ) {
|
||||
// light object
|
||||
} else if ( token[0] == "15" ) {
|
||||
// ignore custom startup locations
|
||||
} else if ( token[0] == "50" || token[0] == "51" || token[0] == "52"
|
||||
|| token[0] == "53" || token[0] == "54" || token[0] == "55"
|
||||
|| token[0] == "56" )
|
||||
{
|
||||
// ignore frequency entries
|
||||
} else if ( token[0] == "99" ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "End of file reached" );
|
||||
} else if ( token[0] == "00" ) {
|
||||
// ??
|
||||
} else {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Unknown line in file: " << line );
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
cout << "last_apt_id.length() = " << last_apt_id.length() << endl;
|
||||
|
||||
if ( !last_apt_id.empty()) {
|
||||
char ctmp, tmpid[32], rwy[32];
|
||||
string id;
|
||||
float lat, lon;
|
||||
int elev = 0;
|
||||
|
||||
if ( runways_list.size() ) {
|
||||
sscanf( runways_list[0].c_str(), "%c %s %s %f %f",
|
||||
&ctmp, tmpid, rwy, &lat, &lon );
|
||||
}
|
||||
|
||||
if ( start_id.length() && start_id == last_apt_id ) {
|
||||
ready_to_go = true;
|
||||
}
|
||||
|
||||
if ( ready_to_go ) {
|
||||
// check point our location
|
||||
char command[256];
|
||||
sprintf( command,
|
||||
"echo before building %s >> %s",
|
||||
last_apt_id.c_str(),
|
||||
lastaptfile.c_str() );
|
||||
system( command );
|
||||
|
||||
// process previous record
|
||||
// process_airport(last_apt_id, runways_list, argv[2]);
|
||||
try {
|
||||
if ( last_apt_type == "16" /* Seaplane base */ ||
|
||||
last_apt_type == "17" /* Heliport */ ) {
|
||||
// skip building heliports and
|
||||
// seaplane bases
|
||||
} else {
|
||||
if( is_in_range( runways_list, min_lat, max_lat, min_lon, max_lon ) ) {
|
||||
build_airport( last_apt_id, elev * SG_FEET_TO_METER,
|
||||
runways_list,
|
||||
beacon_list,
|
||||
tower_list,
|
||||
windsock_list,
|
||||
work_dir, elev_src );
|
||||
}
|
||||
}
|
||||
} catch (sg_exception &e) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Failed to build airport = "
|
||||
<< last_apt_id );
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Exception: "
|
||||
<< e.getMessage() );
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Skipping airport " << id);
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "[FINISHED CORRECTLY]");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_in_range( string_list & runways_raw, float min_lat, float max_lat, float min_lon, float max_lon )
|
||||
{
|
||||
int i;
|
||||
int rwy_count = 0;
|
||||
double apt_lon = 0.0, apt_lat = 0.0;
|
||||
|
||||
for ( i = 0; i < (int)runways_raw.size(); ++i ) {
|
||||
++rwy_count;
|
||||
|
||||
string rwy_str = runways_raw[i];
|
||||
vector<string> token = simgear::strutils::split( rwy_str );
|
||||
|
||||
apt_lat += atof( token[1].c_str() );
|
||||
apt_lon += atof( token[2].c_str() );
|
||||
}
|
||||
|
||||
if( rwy_count > 0 ) {
|
||||
apt_lat /= rwy_count;
|
||||
apt_lon /= rwy_count;
|
||||
}
|
||||
|
||||
if( apt_lat >= min_lat && apt_lat <= max_lat &&
|
||||
apt_lon >= min_lon && apt_lon <= max_lon ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
38
src/Airports/GenAirports850/point2d.cxx
Normal file
38
src/Airports/GenAirports850/point2d.cxx
Normal file
|
@ -0,0 +1,38 @@
|
|||
// point2d.cxx -- 2d coordinate routines
|
||||
//
|
||||
// Written by Curtis Olson, started September 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: point2d.cxx,v 1.2 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "point2d.hxx"
|
||||
|
||||
|
||||
// convert a point from cartesian to polar coordinates
|
||||
Point3D cart_to_polar_2d(const Point3D& in) {
|
||||
Point3D result( sqrt(in.x() * in.x() + in.y() * in.y()),
|
||||
atan2(in.y(), in.x()),
|
||||
0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
39
src/Airports/GenAirports850/point2d.hxx
Normal file
39
src/Airports/GenAirports850/point2d.hxx
Normal file
|
@ -0,0 +1,39 @@
|
|||
// point2d.hxx -- define a 2d point class
|
||||
//
|
||||
// Written by Curtis Olson, started February 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: point2d.hxx,v 1.4 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _POINT2D_HXX
|
||||
#define _POINT2D_HXX
|
||||
|
||||
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <Geometry/point3d.hxx>
|
||||
|
||||
|
||||
// convert a point from cartesian to polar coordinates
|
||||
Point3D cart_to_polar_2d(const Point3D& in);
|
||||
|
||||
|
||||
#endif // _POINT2D_HXX
|
||||
|
||||
|
117
src/Airports/GenAirports850/poly_extra.cxx
Normal file
117
src/Airports/GenAirports850/poly_extra.cxx
Normal file
|
@ -0,0 +1,117 @@
|
|||
// poly_extra.cxx -- Extra polygon manipulation routines
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: poly_extra.cxx,v 1.9 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include <Geometry/poly_support.hxx>
|
||||
|
||||
#include "poly_extra.hxx"
|
||||
|
||||
|
||||
// Divide segment if there are other existing points on it, return the
|
||||
// new polygon
|
||||
void add_intermediate_nodes( int contour, const Point3D& start,
|
||||
const Point3D& end, const TGTriNodes& tmp_nodes,
|
||||
TGPolygon *result )
|
||||
{
|
||||
point_list nodes = tmp_nodes.get_node_list();
|
||||
|
||||
// SG_LOG(SG_GENERAL, SG_DEBUG, " add_intermediate_nodes()");
|
||||
char buf[200];
|
||||
snprintf(buf, 199, " %.7f %.7f %.7f <=> %.7f %.7f %.7f\n",
|
||||
start.x(), start.y(), start.z(), end.x(), end.y(), end.z() );
|
||||
SG_LOG(SG_GENERAL, SG_BULK, buf);
|
||||
|
||||
|
||||
Point3D new_pt;
|
||||
bool found_extra = find_intermediate_node( start, end, nodes, &new_pt );
|
||||
|
||||
if ( found_extra ) {
|
||||
// recurse with two sub segments
|
||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << p0 << " " << nodes[extra_index]
|
||||
// << " " << p1);
|
||||
add_intermediate_nodes( contour, start, new_pt, tmp_nodes,
|
||||
result );
|
||||
|
||||
result->add_node( contour, new_pt );
|
||||
SG_LOG(SG_GENERAL, SG_BULK, " adding = " << new_pt);
|
||||
|
||||
add_intermediate_nodes( contour, new_pt, end, tmp_nodes,
|
||||
result );
|
||||
} else {
|
||||
// this segment does not need to be divided
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Search each segment for additional vertex points that may have been
|
||||
// created elsewhere that lie on the segment and split it there to
|
||||
// avoid "T" intersections.
|
||||
|
||||
TGPolygon add_nodes_to_poly( const TGPolygon& poly,
|
||||
const TGTriNodes& tmp_nodes ) {
|
||||
int i, j;
|
||||
TGPolygon result; result.erase();
|
||||
Point3D p0, p1;
|
||||
|
||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "add_nodes_to_poly");
|
||||
|
||||
for ( i = 0; i < poly.contours(); ++i ) {
|
||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "contour = " << i);
|
||||
for ( j = 0; j < poly.contour_size(i) - 1; ++j ) {
|
||||
p0 = poly.get_pt( i, j );
|
||||
p1 = poly.get_pt( i, j + 1 );
|
||||
|
||||
// add start of segment
|
||||
result.add_node( i, p0 );
|
||||
|
||||
// add intermediate points
|
||||
add_intermediate_nodes( i, p0, p1, tmp_nodes, &result );
|
||||
|
||||
// end of segment is beginning of next segment
|
||||
}
|
||||
p0 = poly.get_pt( i, poly.contour_size(i) - 1 );
|
||||
p1 = poly.get_pt( i, 0 );
|
||||
|
||||
// add start of segment
|
||||
result.add_node( i, p0 );
|
||||
|
||||
// add intermediate points
|
||||
add_intermediate_nodes( i, p0, p1, tmp_nodes, &result );
|
||||
|
||||
// end of segment is beginning of next segment
|
||||
// 5/9/2000 CLO - this results in duplicating the last point
|
||||
// of a contour so I have removed this line.
|
||||
// result.add_node( i, p1 );
|
||||
|
||||
// maintain original hole flag setting
|
||||
result.set_hole_flag( i, poly.get_hole_flag( i ) );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
50
src/Airports/GenAirports850/poly_extra.hxx
Normal file
50
src/Airports/GenAirports850/poly_extra.hxx
Normal file
|
@ -0,0 +1,50 @@
|
|||
// poly_extra.hxx -- Extra polygon manipulation routines
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: poly_extra.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _POLY_EXTRA_HXX
|
||||
#define _POLY_EXTRA_HXX
|
||||
|
||||
|
||||
#include <Geometry/point3d.hxx>
|
||||
|
||||
#include <Geometry/trinodes.hxx>
|
||||
#include <Polygon/polygon.hxx>
|
||||
|
||||
|
||||
// Divide segment if there are other existing points on it, return the
|
||||
// new polygon
|
||||
void add_intermediate_nodes( int contour, const Point3D& start,
|
||||
const Point3D& end, const TGTriNodes& tmp_nodes,
|
||||
TGPolygon *result );
|
||||
|
||||
|
||||
// Search each segment for additional vertex points that may have been
|
||||
// created elsewhere that lie on the segment and split it there to
|
||||
// avoid "T" intersections.
|
||||
|
||||
TGPolygon add_nodes_to_poly( const TGPolygon& poly,
|
||||
const TGTriNodes& tmp_nodes );
|
||||
|
||||
|
||||
#endif // _POLY_EXTRA_HXX
|
73
src/Airports/GenAirports850/process.pl
Executable file
73
src/Airports/GenAirports850/process.pl
Executable file
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# this is a sad testament to building your software off of other
|
||||
# libraries that have bugs (or perhaps less than disired features.)
|
||||
# Unfortunatley I don't know enough about the functionality they
|
||||
# provide to go fix them. Maybe someday.
|
||||
|
||||
# At any rate. This script is a wrapper around the main airport
|
||||
# generation utility. It run it until it finishes or crashes. If it
|
||||
# finishes without saying, yup I'm all done, a crash is assumed. We
|
||||
# re-run the airport generate from the crash point with a different
|
||||
# nudge factor in a sorry attempt to work around the bug.
|
||||
|
||||
# yes, I know this is a really ugly hack, I apologize in advance to
|
||||
# those who might have trouble running these tools on non-unix
|
||||
# platforms, but I'm not sure what else to do at this point. If
|
||||
# someone can fix the polygon clipping library so it doesn't leave
|
||||
# tiny shards of polygons or cracks, I'd be very grateful.
|
||||
|
||||
# So here we go, children under 13 years of age should probably have
|
||||
# parental supervision if playing with something this ugly.
|
||||
|
||||
|
||||
# Edit the following values to set up your preferences:
|
||||
|
||||
$workdir = "/stage/fgfs04/curt/Work";
|
||||
$inputfile = "./default.apt";
|
||||
$binary = "./genapts";
|
||||
$startid = "";
|
||||
|
||||
# end of user configurable section
|
||||
|
||||
|
||||
$done = 0;
|
||||
$nudge = 0;
|
||||
|
||||
while ( ! $done ) {
|
||||
|
||||
# update the nudge value
|
||||
$nudge += 5;
|
||||
if ( $nudge > 40 ) {
|
||||
$nudge = 5;
|
||||
}
|
||||
|
||||
# launch the airport generator
|
||||
|
||||
$command = "$binary --input=$inputfile --work=$workdir --nudge=$nudge";
|
||||
|
||||
if ( $startid ne "" ) {
|
||||
$command .= " --start-id=$startid";
|
||||
}
|
||||
|
||||
print "Executing $command\n";
|
||||
open( PIPE, "$command |" ) || die "Cannot run $command\n";
|
||||
|
||||
while ( <PIPE> ) {
|
||||
if ( m/Id portion/ ) {
|
||||
# print $_;
|
||||
}
|
||||
|
||||
if ( m/\[FINISHED CORRECTLY\]/ ) {
|
||||
$done = 1;
|
||||
print "FINISHED!\n";
|
||||
}
|
||||
}
|
||||
|
||||
close ( PIPE );
|
||||
|
||||
if ( ! $done ) {
|
||||
$startid = `cat last_apt`; chop( $startid );
|
||||
print "Restarting at $startid.\n";
|
||||
}
|
||||
}
|
13
src/Airports/GenAirports850/process.sh
Executable file
13
src/Airports/GenAirports850/process.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#! /bin/bash
|
||||
|
||||
# Previously Skipped: EBPP
|
||||
# Manually removed: NZSP (led to a runway around the world)
|
||||
# Fixed: YSAR (was marked as land airport, but was a heliport)
|
||||
|
||||
WORKDIR=$HOME/workdirs/world_scenery
|
||||
#APTDAT="/home/martin/GIT/fgdata/Airports/apt.dat.gz"
|
||||
#APTDAT="/home/rgerlich/rawdata/apt.dat.gz"
|
||||
APTDAT="/home/rgerlich/rawdata/apt.helidat.gz"
|
||||
SPAT="--nudge=20"
|
||||
|
||||
exec /usr/bin/time genapts --input=$APTDAT --work=$WORKDIR $SPAT > genapts.log 2>&1
|
191
src/Airports/GenAirports850/runway.cxx
Normal file
191
src/Airports/GenAirports850/runway.cxx
Normal file
|
@ -0,0 +1,191 @@
|
|||
// area.c -- routines to assist with inserting "areas" into FG terrain
|
||||
//
|
||||
// Written by Curtis Olson, started March 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: runway.cxx,v 1.18 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "point2d.hxx"
|
||||
|
||||
|
||||
// given a runway center point, length, width, and heading, and
|
||||
// altitude (meters) generate the lon and lat 4 corners using wgs84
|
||||
// math.
|
||||
TGPolygon gen_wgs84_area( Point3D origin,
|
||||
double length_m,
|
||||
double displ1, double displ2,
|
||||
double width_m,
|
||||
double heading_deg,
|
||||
double alt_m,
|
||||
bool add_mid )
|
||||
{
|
||||
TGPolygon result_list;
|
||||
double length_hdg = heading_deg;
|
||||
double left_hdg = length_hdg - 90.0;
|
||||
if ( left_hdg < 0 ) { left_hdg += 360.0; }
|
||||
|
||||
// move to the +l end/center of the runway
|
||||
Point3D ref = origin;
|
||||
double lon, lat, r;
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), length_hdg,
|
||||
length_m / 2.0 - displ2, &lat, &lon, &r );
|
||||
ref = Point3D( lon, lat, 0.0 );
|
||||
|
||||
// move to the l,-w corner (then we add points in a clockwise direction)
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), left_hdg,
|
||||
-width_m / 2.0, &lat, &lon, &r );
|
||||
Point3D p = Point3D( lon, lat, 0.0 );
|
||||
result_list.add_node( 0, p );
|
||||
|
||||
// move to the l,w corner
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), left_hdg,
|
||||
width_m / 2.0, &lat, &lon, &r );
|
||||
p = Point3D( lon, lat, 0.0 );
|
||||
result_list.add_node( 0, p );
|
||||
|
||||
if ( add_mid ) {
|
||||
// move to the 0,w point (then we add points in a clockwise direction)
|
||||
|
||||
ref = origin;
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), left_hdg,
|
||||
width_m / 2.0, &lat, &lon, &r );
|
||||
p = Point3D( lon, lat, 0.0 );
|
||||
result_list.add_node( 0, p );
|
||||
}
|
||||
|
||||
// move to the -l end/center of the runway
|
||||
ref = origin;
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), length_hdg,
|
||||
displ1 - length_m/2.0, &lat, &lon, &r );
|
||||
ref = Point3D( lon, lat, 0.0 );
|
||||
|
||||
// move to the -l,w corner (then we add points in a clockwise direction)
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), left_hdg,
|
||||
width_m / 2.0, &lat, &lon, &r );
|
||||
p = Point3D( lon, lat, 0.0 );
|
||||
result_list.add_node( 0, p );
|
||||
|
||||
// move to the -l,-w corner
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), left_hdg,
|
||||
-width_m / 2.0, &lat, &lon, &r );
|
||||
p = Point3D( lon, lat, 0.0 );
|
||||
result_list.add_node( 0, p );
|
||||
|
||||
if ( add_mid ) {
|
||||
// move to the 0,-w point (then we add points in a clockwise direction)
|
||||
|
||||
ref = origin;
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), left_hdg,
|
||||
-width_m / 2.0, &lat, &lon, &r );
|
||||
p = Point3D( lon, lat, 0.0 );
|
||||
result_list.add_node( 0, p );
|
||||
}
|
||||
|
||||
return result_list;
|
||||
}
|
||||
|
||||
|
||||
// generate an area for a runway with expantion specified as a scale
|
||||
// factor (return result points in degrees)
|
||||
TGPolygon gen_runway_area_w_scale( const TGRunway& runway,
|
||||
double alt_m,
|
||||
double length_scale,
|
||||
double width_scale ) {
|
||||
|
||||
TGPolygon result_list;
|
||||
Point3D origin(runway.lon, runway.lat, 0);
|
||||
|
||||
result_list = gen_wgs84_area( origin,
|
||||
runway.length*length_scale * SG_FEET_TO_METER,
|
||||
0.0, 0.0,
|
||||
runway.width*width_scale * SG_FEET_TO_METER,
|
||||
runway.heading, alt_m, false );
|
||||
|
||||
// display points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Results w/ scale (new way)");
|
||||
for ( int i = 0; i < result_list.contour_size( 0 ); ++i ) {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " " << result_list.get_pt(0, i));
|
||||
}
|
||||
|
||||
return result_list;
|
||||
}
|
||||
|
||||
|
||||
// generate an area for a runway with expansion specified in meters
|
||||
// (return result points in degrees)
|
||||
TGPolygon gen_runway_area_w_extend( const TGRunway& runway,
|
||||
double alt_m,
|
||||
double length_extend,
|
||||
double displ1, double displ2,
|
||||
double width_extend ) {
|
||||
|
||||
TGPolygon result_list;
|
||||
Point3D origin(runway.lon, runway.lat, 0);
|
||||
|
||||
result_list
|
||||
= gen_wgs84_area( origin,
|
||||
runway.length*SG_FEET_TO_METER + 2.0*length_extend,
|
||||
displ1, displ2,
|
||||
runway.width*SG_FEET_TO_METER + 2.0*width_extend,
|
||||
runway.heading, alt_m, false );
|
||||
|
||||
// display points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Results w/ extend (new way)");
|
||||
for ( int i = 0; i < result_list.contour_size( 0 ); ++i ) {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " " << result_list.get_pt(0, i));
|
||||
}
|
||||
|
||||
return result_list;
|
||||
}
|
||||
|
||||
|
||||
// generate an area for a runway and include midpoints
|
||||
TGPolygon gen_runway_w_mid( const TGRunway& runway,
|
||||
double alt_m,
|
||||
double length_extend_m,
|
||||
double width_extend_m ) {
|
||||
TGPolygon result_list;
|
||||
Point3D origin(runway.lon, runway.lat, 0);
|
||||
|
||||
result_list = gen_wgs84_area( origin,
|
||||
runway.length * SG_FEET_TO_METER
|
||||
+ 2.0*length_extend_m,
|
||||
0.0, 0.0,
|
||||
runway.width * SG_FEET_TO_METER
|
||||
+ 2.0 * width_extend_m,
|
||||
runway.heading, alt_m, true );
|
||||
|
||||
// display points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Results w/ mid (new way)");
|
||||
for ( int i = 0; i < result_list.contour_size( 0 ); ++i ) {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " " << result_list.get_pt(0, i));
|
||||
}
|
||||
|
||||
return result_list;
|
||||
}
|
111
src/Airports/GenAirports850/runway.hxx
Normal file
111
src/Airports/GenAirports850/runway.hxx
Normal file
|
@ -0,0 +1,111 @@
|
|||
// runway.hxx -- class to store runway info
|
||||
//
|
||||
// Written by Curtis Olson, started November 1999.
|
||||
//
|
||||
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: runway.hxx,v 1.16 2005-04-20 18:20:15 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _RUNWAY_HXX
|
||||
#define _RUNWAY_HXX
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Geometry/point3d.hxx>
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
|
||||
|
||||
struct TGRunway {
|
||||
std::string rwy_no;
|
||||
|
||||
double lon;
|
||||
double lat;
|
||||
double heading;
|
||||
double length;
|
||||
double width;
|
||||
double disp_thresh1;
|
||||
double disp_thresh2;
|
||||
double stopway1;
|
||||
double stopway2;
|
||||
|
||||
std::string lighting_flags;
|
||||
int surface_code;
|
||||
std::string shoulder_code;
|
||||
int marking_code;
|
||||
double smoothness;
|
||||
bool dist_remaining;
|
||||
|
||||
double gs_angle1;
|
||||
double gs_angle2;
|
||||
|
||||
TGPolygon threshold;
|
||||
TGPolygon tens, tens_margin, ones, ones_margin;
|
||||
TGPolygon letter, letter_margin_left, letter_margin_right;
|
||||
TGPolygon pre_td_zone;
|
||||
TGPolygon td3_zone, td2_zone, td1a_zone, td1b_zone;
|
||||
TGPolygon aim_point;
|
||||
|
||||
bool really_taxiway;
|
||||
bool generated;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector < TGRunway > runway_list;
|
||||
typedef runway_list::iterator runway_list_iterator;
|
||||
typedef runway_list::const_iterator const_runway_list_iterator;
|
||||
|
||||
|
||||
// given a runway center point, length, width, and heading, and
|
||||
// altitude (meters) generate the lon and lat 4 corners using wgs84
|
||||
// math.
|
||||
TGPolygon gen_wgs84_area( Point3D origin,
|
||||
double length_m,
|
||||
double displ1, double displ2,
|
||||
double width_m,
|
||||
double heading_deg,
|
||||
double alt_m,
|
||||
bool add_mid );
|
||||
|
||||
// generate an area for a runway with expantion specified as a scale
|
||||
// factor (return result points in degrees)
|
||||
TGPolygon gen_runway_area_w_scale( const TGRunway& runway,
|
||||
double alt_m,
|
||||
double length_scale = 1.0,
|
||||
double width_scale = 1.0 );
|
||||
|
||||
// generate an area for a runway with expansion specified in meters
|
||||
// (return result points in degrees)
|
||||
TGPolygon gen_runway_area_w_extend( const TGRunway& runway,
|
||||
double alt_m,
|
||||
double length_extend,
|
||||
double displ1, double displ2,
|
||||
double width_extend );
|
||||
|
||||
|
||||
// generate an area for half a runway
|
||||
TGPolygon gen_runway_w_mid( const TGRunway& runway,
|
||||
double alt_m,
|
||||
double length_extend_m,
|
||||
double width_extend_m );
|
||||
|
||||
|
||||
#endif // _RUNWAY_HXX
|
327
src/Airports/GenAirports850/rwy_common.cxx
Normal file
327
src/Airports/GenAirports850/rwy_common.cxx
Normal file
|
@ -0,0 +1,327 @@
|
|||
// rwy_common.cxx -- Common runway generation routines
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_common.cxx,v 1.12 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "global.hxx"
|
||||
#include "poly_extra.hxx"
|
||||
#include "rwy_common.hxx"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
void gen_number_block( const TGRunway& rwy_info,
|
||||
const string& material,
|
||||
TGPolygon poly, double heading, int num,
|
||||
double start_pct, double end_pct,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum )
|
||||
{
|
||||
char tex1[32]; tex1[0] = '\0';
|
||||
char tex2[32]; tex2[0] = '\0';
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway num = " << num);
|
||||
|
||||
if ( num == 0 ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Ack! Someone passed in a runway number of '0'" );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ( num == 11 ) {
|
||||
sprintf( tex1, "11" );
|
||||
} else if ( num < 10 ) {
|
||||
sprintf( tex1, "%dc", num );
|
||||
} else {
|
||||
sprintf( tex1, "%dl", num / 10 );
|
||||
sprintf( tex2, "%dr", num - (num / 10 * 10));
|
||||
}
|
||||
|
||||
// printf("tex1 = '%s' tex2 = '%s'\n", tex1, tex2);
|
||||
|
||||
if ( num < 10 ) {
|
||||
gen_runway_section( rwy_info, poly,
|
||||
start_pct, end_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
material, tex1,
|
||||
rwy_polys, texparams, accum );
|
||||
} else if ( num == 11 ) {
|
||||
gen_runway_section( rwy_info, poly,
|
||||
start_pct, end_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
material, tex1,
|
||||
rwy_polys, texparams, accum );
|
||||
} else {
|
||||
gen_runway_section( rwy_info, poly,
|
||||
start_pct, end_pct,
|
||||
0.0, 0.5,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
material, tex1,
|
||||
rwy_polys, texparams, accum );
|
||||
gen_runway_section( rwy_info, poly,
|
||||
start_pct, end_pct,
|
||||
0.5, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
material, tex2,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
}
|
||||
|
||||
// generate the runway stopway
|
||||
void gen_runway_stopway( const TGRunway& rwy_info,
|
||||
const TGPolygon& runway_a,
|
||||
const TGPolygon& runway_b,
|
||||
const string& prefix,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon* accum ) {
|
||||
const float length = rwy_info.length / 2.0 + 2.0;
|
||||
double start1_pct = 0.0;
|
||||
double start2_pct = 0.0;
|
||||
double end1_pct = 0.0;
|
||||
double end2_pct = 0.0;
|
||||
double part_len = 0.0;
|
||||
|
||||
int count=0;
|
||||
int i=0;
|
||||
|
||||
if (rwy_info.stopway1 > 0.0) {
|
||||
/* Generate approach end stopway */
|
||||
count = (int) (rwy_info.stopway1 * 2.0/ rwy_info.width);
|
||||
if(count < 1) count = 1;
|
||||
part_len = rwy_info.stopway1 / (double) count;
|
||||
for(i=0;i<count;i++)
|
||||
{
|
||||
start1_pct=end1_pct;
|
||||
end1_pct = start1_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info,
|
||||
runway_b,
|
||||
- end1_pct, -start1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0, //last number is lengthwise
|
||||
rwy_info.heading + 180.0,
|
||||
prefix,
|
||||
"stopway",
|
||||
rwy_polys,
|
||||
texparams,
|
||||
accum);
|
||||
}
|
||||
}
|
||||
if (rwy_info.stopway2 > 0.0) {
|
||||
/* Generate reciprocal end stopway */
|
||||
count = (int) (rwy_info.stopway2 * 2.0 / rwy_info.width);
|
||||
if(count < 1) count = 1;
|
||||
part_len = rwy_info.stopway2 / (double) count;
|
||||
for(i=0;i<count;i++)
|
||||
{
|
||||
start2_pct=end2_pct;
|
||||
end2_pct = start2_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info,
|
||||
runway_a,
|
||||
- end2_pct, -start2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
prefix,
|
||||
"stopway",
|
||||
rwy_polys,
|
||||
texparams,
|
||||
accum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate a section of runway
|
||||
void gen_runway_section( const TGRunway& rwy_info,
|
||||
const TGPolygon& runway,
|
||||
double startl_pct, double endl_pct,
|
||||
double startw_pct, double endw_pct,
|
||||
double minu, double maxu, double minv, double maxv,
|
||||
double heading,
|
||||
const string& prefix,
|
||||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum ) {
|
||||
|
||||
int j, k;
|
||||
|
||||
Point3D a0 = runway.get_pt(0, 1);
|
||||
Point3D a1 = runway.get_pt(0, 2);
|
||||
Point3D a2 = runway.get_pt(0, 0);
|
||||
Point3D a3 = runway.get_pt(0, 3);
|
||||
|
||||
if ( startl_pct > 0.0 ) {
|
||||
startl_pct -= nudge * SG_EPSILON;
|
||||
}
|
||||
if ( endl_pct < 1.0 ) {
|
||||
endl_pct += nudge * SG_EPSILON;
|
||||
}
|
||||
|
||||
if ( endl_pct > 1.0 ) {
|
||||
endl_pct = 1.0;
|
||||
}
|
||||
|
||||
// partial "w" percentages could introduce "T" intersections which
|
||||
// we compensate for later, but could still cause problems now
|
||||
// with our polygon clipping code. This attempts to compensate
|
||||
// for that by nudging the areas a bit bigger so we don't end up
|
||||
// with polygon slivers.
|
||||
if ( startw_pct > 0.0 || endw_pct < 1.0 ) {
|
||||
if ( startw_pct > 0.0 ) {
|
||||
startw_pct -= nudge * SG_EPSILON;
|
||||
}
|
||||
if ( endw_pct < 1.0 ) {
|
||||
endw_pct += nudge * SG_EPSILON;
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "start len % = " << startl_pct
|
||||
<< " end len % = " << endl_pct);
|
||||
|
||||
double dlx, dly;
|
||||
|
||||
dlx = a1.x() - a0.x();
|
||||
dly = a1.y() - a0.y();
|
||||
|
||||
Point3D t0 = Point3D( a0.x() + dlx * startl_pct,
|
||||
a0.y() + dly * startl_pct, 0);
|
||||
Point3D t1 = Point3D( a0.x() + dlx * endl_pct,
|
||||
a0.y() + dly * endl_pct, 0);
|
||||
|
||||
dlx = a3.x() - a2.x();
|
||||
dly = a3.y() - a2.y();
|
||||
|
||||
Point3D t2 = Point3D( a2.x() + dlx * startl_pct,
|
||||
a2.y() + dly * startl_pct, 0);
|
||||
|
||||
Point3D t3 = Point3D( a2.x() + dlx * endl_pct,
|
||||
a2.y() + dly * endl_pct, 0);
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "start wid % = " << startw_pct
|
||||
<< " end wid % = " << endw_pct);
|
||||
|
||||
double dwx, dwy;
|
||||
|
||||
dwx = t0.x() - t2.x();
|
||||
dwy = t0.y() - t2.y();
|
||||
|
||||
Point3D p0 = Point3D( t2.x() + dwx * startw_pct,
|
||||
t2.y() + dwy * startw_pct, 0);
|
||||
|
||||
Point3D p1 = Point3D( t2.x() + dwx * endw_pct,
|
||||
t2.y() + dwy * endw_pct, 0);
|
||||
|
||||
dwx = t1.x() - t3.x();
|
||||
dwy = t1.y() - t3.y();
|
||||
|
||||
Point3D p2 = Point3D( t3.x() + dwx * startw_pct,
|
||||
t3.y() + dwy * startw_pct, 0);
|
||||
|
||||
Point3D p3 = Point3D( t3.x() + dwx * endw_pct,
|
||||
t3.y() + dwy * endw_pct, 0);
|
||||
|
||||
TGPolygon section;
|
||||
section.erase();
|
||||
|
||||
section.add_node( 0, p2 );
|
||||
section.add_node( 0, p0 );
|
||||
section.add_node( 0, p1 );
|
||||
section.add_node( 0, p3 );
|
||||
|
||||
// print runway points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "pre clipped runway pts " << prefix << material);
|
||||
for ( j = 0; j < section.contours(); ++j ) {
|
||||
for ( k = 0; k < section.contour_size( j ); ++k ) {
|
||||
Point3D p = section.get_pt(j, k);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
}
|
||||
|
||||
// Clip the new polygon against what ever has already been created.
|
||||
TGPolygon clipped = tgPolygonDiff( section, *accum );
|
||||
|
||||
// Split long edges to create an object that can better flow with
|
||||
// the surface terrain
|
||||
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
|
||||
|
||||
// Create the final output and push on to the runway super_polygon
|
||||
// list
|
||||
TGSuperPoly sp;
|
||||
sp.erase();
|
||||
sp.set_poly( split );
|
||||
sp.set_material( prefix + material );
|
||||
rwy_polys->push_back( sp );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "section = " << clipped.contours());
|
||||
*accum = tgPolygonUnion( section, *accum );
|
||||
|
||||
// Store away what we need to know for texture coordinate
|
||||
// calculation. (CLO 10/20/02: why can't we calculate texture
|
||||
// coordinates here? Oh, becuase later we need to massage the
|
||||
// polygons to avoid "T" intersections and clean up other
|
||||
// potential artifacts and we may add or remove points and need to
|
||||
// do new texture coordinate calcs later.
|
||||
|
||||
// we add 2' to the length for texture overlap. This puts the
|
||||
// lines on the texture back to the edge of the runway where they
|
||||
// belong.
|
||||
double len = rwy_info.length / 2.0 + 2;
|
||||
double sect_len = len * ( endl_pct - startl_pct );
|
||||
|
||||
// we add 2' to both sides of the runway (4' total) for texture
|
||||
// overlap. This puts the lines on the texture back to the edge
|
||||
// of the runway where they belong.
|
||||
double wid = rwy_info.width + 4;
|
||||
double sect_wid = wid * ( endw_pct - startw_pct );
|
||||
|
||||
TGTexParams tp;
|
||||
tp = TGTexParams( p0,
|
||||
sect_wid * SG_FEET_TO_METER,
|
||||
sect_len * SG_FEET_TO_METER,
|
||||
heading );
|
||||
tp.set_minu( minu );
|
||||
tp.set_maxu( maxu );
|
||||
tp.set_minv( minv );
|
||||
tp.set_maxv( maxv );
|
||||
texparams->push_back( tp );
|
||||
|
||||
// print runway points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts " << prefix + material);
|
||||
for ( j = 0; j < clipped.contours(); ++j ) {
|
||||
for ( k = 0; k < clipped.contour_size( j ); ++k ) {
|
||||
Point3D p = clipped.get_pt(j, k);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
}
|
||||
}
|
67
src/Airports/GenAirports850/rwy_common.hxx
Normal file
67
src/Airports/GenAirports850/rwy_common.hxx
Normal file
|
@ -0,0 +1,67 @@
|
|||
// rwy_common.hxx -- Common runway generation routines
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_common.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _RWY_COMMON_HXX
|
||||
#define _RWY_COMMON_HXX
|
||||
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "texparams.hxx"
|
||||
|
||||
|
||||
void gen_number_block( const TGRunway& rwy_info,
|
||||
const std::string& material,
|
||||
TGPolygon poly, double heading, int num,
|
||||
double start_pct, double end_pct,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum );
|
||||
|
||||
// generate the runway stopway
|
||||
void gen_runway_stopway( const TGRunway& rwy_info,
|
||||
const TGPolygon& runway_a,
|
||||
const TGPolygon& runway_b,
|
||||
const std::string& prefix,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon* accum );
|
||||
|
||||
// generate a section of runway
|
||||
void gen_runway_section( const TGRunway& rwy_info,
|
||||
const TGPolygon& runway,
|
||||
double startl_pct, double endl_pct,
|
||||
double startw_pct, double endw_pct,
|
||||
double minu, double maxu, double minv, double maxv,
|
||||
double heading,
|
||||
const std::string& prefix,
|
||||
const std::string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum );
|
||||
|
||||
|
||||
#endif // _RWY_COMMON_HXX
|
619
src/Airports/GenAirports850/rwy_gen.cxx
Normal file
619
src/Airports/GenAirports850/rwy_gen.cxx
Normal file
|
@ -0,0 +1,619 @@
|
|||
// rwy_prec.cxx -- Build a precision runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_prec.cxx,v 1.18 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "rwy_common.hxx"
|
||||
#include "rwy_nonprec.hxx"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
// generate a precision approach runway. The routine modifies
|
||||
// rwy_polys, texparams, and accum. For specific details and
|
||||
// dimensions of precision runway markings, please refer to FAA
|
||||
// document AC 150/5340-1H
|
||||
|
||||
void gen_precision_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Building runway = " << rwy_info.rwy_no );
|
||||
|
||||
//
|
||||
// Generate the basic runway outlines
|
||||
//
|
||||
|
||||
int i;
|
||||
|
||||
TGPolygon runway = gen_runway_w_mid( rwy_info, alt_m,
|
||||
2 * SG_FEET_TO_METER,
|
||||
2 * SG_FEET_TO_METER );
|
||||
|
||||
// runway half "a" (actually the reverse half)
|
||||
TGPolygon runway_a;
|
||||
runway_a.erase();
|
||||
runway_a.add_node( 0, runway.get_pt(0, 0) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 1) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 2) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 5) );
|
||||
|
||||
|
||||
// runway half "b" (actually the forward half)
|
||||
TGPolygon runway_b;
|
||||
runway_b.erase();
|
||||
runway_b.add_node( 0, runway.get_pt(0, 3) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 4) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 5) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 2) );
|
||||
|
||||
Point3D p;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (a half)");
|
||||
for ( i = 0; i < runway_a.contour_size( 0 ); ++i ) {
|
||||
p = runway_a.get_pt(0, i);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (b half)");
|
||||
for ( i = 0; i < runway_b.contour_size( 0 ); ++i ) {
|
||||
p = runway_b.get_pt(0, i);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
|
||||
//
|
||||
// Setup some variables and values to help us chop up the runway
|
||||
// into its various sections
|
||||
//
|
||||
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
// we add 2' to the length for texture overlap. This puts the
|
||||
// lines on the texture back to the edge of the runway where they
|
||||
// belong.
|
||||
double length = rwy_info.length / 2.0 + 2.0;
|
||||
if ( length < 3075 ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Runway " << rwy_info.rwy_no << " is not long enough ("
|
||||
<< rwy_info.length << ") for precision markings!");
|
||||
}
|
||||
|
||||
double start1_pct = 0.0;
|
||||
double start2_pct = 0.0;
|
||||
double end1_pct = 0.0;
|
||||
double end2_pct = 0.0;
|
||||
|
||||
//
|
||||
// Displaced threshold if it exists
|
||||
//
|
||||
|
||||
if ( rwy_info.disp_thresh1 > 0.0 ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Forward displaced threshold = "
|
||||
<< rwy_info.disp_thresh1 );
|
||||
|
||||
// reserve 90' for final arrows
|
||||
double thresh = rwy_info.disp_thresh1 - 90.0;
|
||||
|
||||
// number of full center arrows
|
||||
int count = (int)(thresh / 200.0);
|
||||
|
||||
// length of starting partial arrow
|
||||
double part_len = thresh - ( count * 200.0 );
|
||||
double tex_pct = (200.0 - part_len) / 200.0;
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, tex_pct, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// main chunks
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// final arrows
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_arrows",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( rwy_info.disp_thresh2 > 0.0 ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Reverse displaced threshold = "
|
||||
<< rwy_info.disp_thresh2 );
|
||||
|
||||
// reserve 90' for final arrows
|
||||
double thresh = rwy_info.disp_thresh2 - 90.0;
|
||||
|
||||
// number of full center arrows
|
||||
int count = (int)(thresh / 200.0);
|
||||
|
||||
// length of starting partial arrow
|
||||
double part_len = thresh - ( count * 200.0 );
|
||||
double tex_pct = (200.0 - part_len) / 200.0;
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, tex_pct, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// main chunks
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// final arrows
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_arrows",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Threshold
|
||||
//
|
||||
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 202.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "threshold",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 202.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "threshold",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
//
|
||||
// Runway designation letter
|
||||
//
|
||||
|
||||
int len = rwy_info.rwy_no.length();
|
||||
string letter = "";
|
||||
string rev_letter = "";
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
string tmp = rwy_info.rwy_no.substr(i, 1);
|
||||
if ( tmp == "L" ) {
|
||||
letter = "L";
|
||||
rev_letter = "R";
|
||||
} else if ( tmp == "R" ) {
|
||||
letter = "R";
|
||||
rev_letter = "L";
|
||||
} else if ( tmp == "C" ) {
|
||||
letter = "C";
|
||||
rev_letter = "C";
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway designation = " << rwy_info.rwy_no);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway designation letter = " << letter);
|
||||
|
||||
if ( !letter.empty() ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, rev_letter,
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, letter,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Runway designation number(s)
|
||||
//
|
||||
|
||||
len = rwy_info.rwy_no.length();
|
||||
string snum = rwy_info.rwy_no;
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
string tmp = rwy_info.rwy_no.substr(i, 1);
|
||||
if ( tmp == "L" || tmp == "R" || tmp == "C" || tmp == " " ) {
|
||||
snum = rwy_info.rwy_no.substr(0, i);
|
||||
}
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Runway num = '" << snum << "'");
|
||||
int num = atoi( snum.c_str() );
|
||||
while ( num <= 0 ) {
|
||||
num += 36;
|
||||
}
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 80.0 / length );
|
||||
gen_number_block( rwy_info, material, runway_b, rwy_info.heading + 180.0,
|
||||
num, start2_pct, end2_pct, rwy_polys, texparams, accum );
|
||||
|
||||
num += 18;
|
||||
while ( num > 36 ) {
|
||||
num -= 36;
|
||||
}
|
||||
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 80.0 / length );
|
||||
gen_number_block( rwy_info, material, runway_a, rwy_info.heading,
|
||||
num, start1_pct, end1_pct, rwy_polys, texparams, accum );
|
||||
|
||||
//
|
||||
// Touch down zone x3
|
||||
//
|
||||
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 380 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "tz_three",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 380 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "tz_three",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// add a section of center stripe
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
//
|
||||
// Aiming point
|
||||
//
|
||||
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "aim",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "aim",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
//
|
||||
// Touch down zone x2 (first)
|
||||
//
|
||||
|
||||
if ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "tz_two_a",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "tz_two_a",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// add a section of center stripe
|
||||
if ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Touch down zone x2 (second)
|
||||
//
|
||||
|
||||
if ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "tz_two_b",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "tz_two_b",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// add a section of center stripe
|
||||
if ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Touch down zone x1 (first)
|
||||
//
|
||||
|
||||
if ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "tz_one_a",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "tz_one_a",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// add a section of center stripe
|
||||
if ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Touch down zone x1 (second)
|
||||
//
|
||||
|
||||
if ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "tz_one_b",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "tz_one_b",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// The rest ...
|
||||
//
|
||||
|
||||
// fit the 'rest' texture in as many times as will go evenly into
|
||||
// the remaining distance so we don't end up with a super short
|
||||
// section at the end.
|
||||
double ideal_rest_inc = ( 200.0 / length );
|
||||
int divs = (int)((1.0 - end1_pct) / ideal_rest_inc) + 1;
|
||||
double rest1_inc = (1.0 - end1_pct) / divs;
|
||||
|
||||
while ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + rest1_inc;
|
||||
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
ideal_rest_inc = ( 200.0 / length );
|
||||
divs = (int)((1.0 - end2_pct) / ideal_rest_inc) + 1;
|
||||
double rest2_inc = (1.0 - end2_pct) / divs;
|
||||
|
||||
while ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + rest2_inc;
|
||||
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
gen_runway_stopway( rwy_info, runway_a, runway_b,
|
||||
material,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
49
src/Airports/GenAirports850/rwy_gen.hxx
Normal file
49
src/Airports/GenAirports850/rwy_gen.hxx
Normal file
|
@ -0,0 +1,49 @@
|
|||
// rwy_prec.hxx -- Build a precision runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_prec.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _RWY_PREC_HXX
|
||||
#define _RWY_PREC_HXX
|
||||
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "texparams.hxx"
|
||||
|
||||
|
||||
// generate a precision approach runway. The routine modifies
|
||||
// rwy_polys, texparams, and accum. For specific details and
|
||||
// dimensions of precision runway markings, please refer to FAA
|
||||
// document AC 150/5340-1H
|
||||
|
||||
void gen_precision_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const std::string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum );
|
||||
|
||||
|
||||
#endif // _RWY_PREC_HXX
|
417
src/Airports/GenAirports850/rwy_nonprec.cxx
Normal file
417
src/Airports/GenAirports850/rwy_nonprec.cxx
Normal file
|
@ -0,0 +1,417 @@
|
|||
// rwy_nonprec.cxx -- Build a non-precision runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_nonprec.cxx,v 1.16 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "rwy_common.hxx"
|
||||
#include "rwy_nonprec.hxx"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
// generate a non-precision approach runway. The routine modifies
|
||||
// rwy_polys, texparams, and accum. For specific details and
|
||||
// dimensions of precision runway markings, please refer to FAA
|
||||
// document AC 150/5340-1H
|
||||
|
||||
void gen_non_precision_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
//
|
||||
// Generate the basic runway outlines
|
||||
//
|
||||
|
||||
TGPolygon runway = gen_runway_w_mid( rwy_info, alt_m,
|
||||
2 * SG_FEET_TO_METER,
|
||||
2 * SG_FEET_TO_METER );
|
||||
|
||||
// runway half "a"
|
||||
TGPolygon runway_a;
|
||||
runway_a.erase();
|
||||
runway_a.add_node( 0, runway.get_pt(0, 0) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 1) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 2) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 5) );
|
||||
|
||||
// runway half "b"
|
||||
TGPolygon runway_b;
|
||||
runway_b.erase();
|
||||
runway_b.add_node( 0, runway.get_pt(0, 3) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 4) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 5) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 2) );
|
||||
|
||||
Point3D p;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (a half)");
|
||||
for ( j = 0; j < runway_a.contour_size( 0 ); ++j ) {
|
||||
p = runway_a.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (b half)");
|
||||
for ( j = 0; j < runway_b.contour_size( 0 ); ++j ) {
|
||||
p = runway_b.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
|
||||
//
|
||||
// Setup some variables and values to help us chop up the runway
|
||||
// into its various sections
|
||||
//
|
||||
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
// we add 2' to the length for texture overlap. This puts the
|
||||
// lines on the texture back to the edge of the runway where they
|
||||
// belong.
|
||||
double length = rwy_info.length / 2.0 + 2.0;
|
||||
if ( length < 1150 ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"This runway is not long enough for non-precision markings!");
|
||||
}
|
||||
|
||||
double start1_pct = 0.0;
|
||||
double start2_pct = 0.0;
|
||||
double end1_pct = 0.0;
|
||||
double end2_pct = 0.0;
|
||||
|
||||
//
|
||||
// Displaced threshold if it exists
|
||||
//
|
||||
|
||||
if ( rwy_info.disp_thresh1 > 0.0 ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Forward displaced threshold = "
|
||||
<< rwy_info.disp_thresh1 );
|
||||
|
||||
// reserve 90' for final arrows
|
||||
double thresh = rwy_info.disp_thresh1 - 90.0;
|
||||
|
||||
// number of full center arrows
|
||||
int count = (int)(thresh / 200.0);
|
||||
|
||||
// length of starting partial arrow
|
||||
double part_len = thresh - ( count * 200.0 );
|
||||
double tex_pct = (200.0 - part_len) / 200.0;
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, tex_pct, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// main chunks
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// final arrows
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_arrows",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( rwy_info.disp_thresh2 > 0.0 ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Reverse displaced threshold = "
|
||||
<< rwy_info.disp_thresh2 );
|
||||
|
||||
// reserve 90' for final arrows
|
||||
double thresh = rwy_info.disp_thresh2 - 90.0;
|
||||
|
||||
// number of full center arrows
|
||||
int count = (int)(thresh / 200.0);
|
||||
|
||||
// length of starting partial arrow
|
||||
double part_len = thresh - ( count * 200.0 );
|
||||
double tex_pct = (200.0 - part_len) / 200.0;
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, tex_pct, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// main chunks
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// final arrows
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_arrows",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Threshold
|
||||
//
|
||||
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 202.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "threshold",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 202.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "threshold",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
//
|
||||
// Runway designation letter
|
||||
//
|
||||
|
||||
int len = rwy_info.rwy_no.length();
|
||||
string letter = "";
|
||||
string rev_letter = "";
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
string tmp = rwy_info.rwy_no.substr(i, 1);
|
||||
if ( tmp == "L" ) {
|
||||
letter = "L";
|
||||
rev_letter = "R";
|
||||
} else if ( tmp == "R" ) {
|
||||
letter = "R";
|
||||
rev_letter = "L";
|
||||
} else if ( tmp == "C" ) {
|
||||
letter = "C";
|
||||
rev_letter = "C";
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway designation = " << rwy_info.rwy_no);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway designation letter = " << letter);
|
||||
|
||||
if ( !letter.empty() ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, rev_letter,
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, letter,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Runway designation number(s)
|
||||
//
|
||||
|
||||
len = rwy_info.rwy_no.length();
|
||||
string snum = rwy_info.rwy_no;
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
string tmp = rwy_info.rwy_no.substr(i, 1);
|
||||
if ( tmp == "L" || tmp == "R" || tmp == "C" || tmp == " " ) {
|
||||
snum = rwy_info.rwy_no.substr(0, i);
|
||||
}
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Runway num = '" << snum << "'");
|
||||
int num = atoi( snum.c_str() );
|
||||
while ( num <= 0 ) {
|
||||
num += 36;
|
||||
}
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 80.0 / length );
|
||||
gen_number_block( rwy_info, material, runway_b, rwy_info.heading + 180.0,
|
||||
num, start2_pct, end2_pct, rwy_polys, texparams, accum );
|
||||
|
||||
num += 18;
|
||||
while ( num > 36 ) {
|
||||
num -= 36;
|
||||
}
|
||||
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 80.0 / length );
|
||||
gen_number_block( rwy_info, material, runway_a, rwy_info.heading,
|
||||
num, start1_pct, end1_pct, rwy_polys, texparams, accum );
|
||||
|
||||
if ( true ) {
|
||||
//
|
||||
// Intermediate area before aiming point ...
|
||||
//
|
||||
|
||||
for ( i = 0; i < 3; ++i ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "centerline",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "centerline",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Aiming point
|
||||
//
|
||||
|
||||
if ( end1_pct >= 1.0 ) {
|
||||
return;
|
||||
}
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "aim",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
if ( end2_pct >= 1.0 ) {
|
||||
return;
|
||||
}
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "aim",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// The rest ...
|
||||
//
|
||||
|
||||
// fit the 'rest' texture in as many times as will go evenly into
|
||||
// the remaining distance so we don't end up with a super short
|
||||
// section at the end.
|
||||
double ideal_rest_inc = ( 200.0 / length );
|
||||
int divs = (int)((1.0 - end1_pct) / ideal_rest_inc) + 1;
|
||||
double rest1_inc = (1.0 - end1_pct) / divs;
|
||||
|
||||
while ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + rest1_inc;
|
||||
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
ideal_rest_inc = ( 200.0 / length );
|
||||
divs = (int)((1.0 - end2_pct) / ideal_rest_inc) + 1;
|
||||
double rest2_inc = (1.0 - end2_pct) / divs;
|
||||
|
||||
while ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + rest2_inc;
|
||||
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
gen_runway_stopway( rwy_info, runway_a, runway_b,
|
||||
material,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
49
src/Airports/GenAirports850/rwy_nonprec.hxx
Normal file
49
src/Airports/GenAirports850/rwy_nonprec.hxx
Normal file
|
@ -0,0 +1,49 @@
|
|||
// rwy_nonprec.hxx -- Build a non-precision runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_nonprec.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _RWY_NONPREC_HXX
|
||||
#define _RWY_NONPREC_HXX
|
||||
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "texparams.hxx"
|
||||
|
||||
|
||||
// generate a non-precision approach runway. The routine modifies
|
||||
// rwy_polys, texparams, and accum. For specific details and
|
||||
// dimensions of precision runway markings, please refer to FAA
|
||||
// document AC 150/5340-1H
|
||||
|
||||
void gen_non_precision_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const std::string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum );
|
||||
|
||||
|
||||
#endif // _RWY_NONPREC_HXX
|
139
src/Airports/GenAirports850/rwy_simple.cxx
Normal file
139
src/Airports/GenAirports850/rwy_simple.cxx
Normal file
|
@ -0,0 +1,139 @@
|
|||
// rwy_simple.cxx -- Build a simple (non-marked) runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_simple.cxx,v 1.12 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "poly_extra.hxx"
|
||||
#include "rwy_common.hxx"
|
||||
#include "texparams.hxx"
|
||||
#include "rwy_nonprec.hxx"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
// generate a simple runway. The routine modifies rwy_polys,
|
||||
// texparams, and accum
|
||||
void gen_simple_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum )
|
||||
{
|
||||
int j, k;
|
||||
|
||||
TGPolygon runway = gen_runway_w_mid( rwy_info, alt_m, 0.0, 0.0 );
|
||||
|
||||
// runway half "a"
|
||||
TGPolygon runway_a;
|
||||
runway_a.erase();
|
||||
runway_a.add_node( 0, runway.get_pt(0, 0) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 1) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 2) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 5) );
|
||||
|
||||
// runway half "b"
|
||||
TGPolygon runway_b;
|
||||
runway_b.erase();
|
||||
runway_b.add_node( 0, runway.get_pt(0, 5) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 2) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 3) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 4) );
|
||||
|
||||
Point3D p;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (a half)");
|
||||
for ( j = 0; j < runway_a.contour_size( 0 ); ++j ) {
|
||||
p = runway_a.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (b half)");
|
||||
for ( j = 0; j < runway_b.contour_size( 0 ); ++j ) {
|
||||
p = runway_b.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
TGPolygon clipped_a = tgPolygonDiff( runway_a, *accum );
|
||||
TGPolygon split_a = tgPolygonSplitLongEdges( clipped_a, 400.0 );
|
||||
sp.erase();
|
||||
sp.set_poly( split_a );
|
||||
sp.set_material( material );
|
||||
rwy_polys->push_back( sp );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped_a = " << clipped_a.contours());
|
||||
*accum = tgPolygonUnion( runway_a, *accum );
|
||||
tp = TGTexParams( runway_a.get_pt(0,0),
|
||||
rwy_info.width * SG_FEET_TO_METER,
|
||||
rwy_info.length * SG_FEET_TO_METER / 2.0,
|
||||
rwy_info.heading );
|
||||
texparams->push_back( tp );
|
||||
|
||||
TGPolygon clipped_b = tgPolygonDiff( runway_b, *accum );
|
||||
TGPolygon split_b = tgPolygonSplitLongEdges( clipped_b, 400.0 );
|
||||
sp.erase();
|
||||
sp.set_poly( split_b );
|
||||
sp.set_material( material );
|
||||
rwy_polys->push_back( sp );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped_b = " << clipped_b.contours());
|
||||
*accum = tgPolygonUnion( runway_b, *accum );
|
||||
tp = TGTexParams( runway_b.get_pt(0,2),
|
||||
rwy_info.width * SG_FEET_TO_METER,
|
||||
rwy_info.length * SG_FEET_TO_METER / 2.0,
|
||||
rwy_info.heading + 180.0 );
|
||||
texparams->push_back( tp );
|
||||
|
||||
#if 0
|
||||
// after clip, but before removing T intersections
|
||||
char tmpa[256], tmpb[256];
|
||||
sprintf( tmpa, "a%d", i );
|
||||
sprintf( tmpb, "b%d", i );
|
||||
write_polygon( clipped_a, tmpa );
|
||||
write_polygon( clipped_b, tmpb );
|
||||
#endif
|
||||
|
||||
// print runway points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts (a)");
|
||||
for ( j = 0; j < clipped_a.contours(); ++j ) {
|
||||
for ( k = 0; k < clipped_a.contour_size( j ); ++k ) {
|
||||
p = clipped_a.get_pt(j, k);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
}
|
||||
|
||||
// print runway points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts (b)");
|
||||
for ( j = 0; j < clipped_b.contours(); ++j ) {
|
||||
for ( k = 0; k < clipped_b.contour_size( j ); ++k ) {
|
||||
p = clipped_b.get_pt(j, k);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
}
|
||||
|
||||
gen_runway_stopway( rwy_info, runway_a, runway_b,
|
||||
material,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
46
src/Airports/GenAirports850/rwy_simple.hxx
Normal file
46
src/Airports/GenAirports850/rwy_simple.hxx
Normal file
|
@ -0,0 +1,46 @@
|
|||
// rwy_simple.hxx -- Build a simple (non-marked) runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_simple.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _RWY_SIMPLE_HXX
|
||||
#define _RWY_SIMPLE_HXX
|
||||
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "texparams.hxx"
|
||||
|
||||
|
||||
// generate a simple runway. The routine modifies rwy_polys,
|
||||
// texparams, and accum
|
||||
void gen_simple_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const std::string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum );
|
||||
|
||||
|
||||
#endif // _RWY_SIMPLE_HXX
|
426
src/Airports/GenAirports850/rwy_visual.cxx
Normal file
426
src/Airports/GenAirports850/rwy_visual.cxx
Normal file
|
@ -0,0 +1,426 @@
|
|||
// rwy_visual.cxx -- Build a visual approach runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_visual.cxx,v 1.18 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "rwy_common.hxx"
|
||||
#include "rwy_visual.hxx"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
// generate a visual approach runway. The routine modifies rwy_polys,
|
||||
// texparams, and accum. For specific details and dimensions of
|
||||
// precision runway markings, please refer to FAA document AC
|
||||
// 150/5340-1H
|
||||
|
||||
void gen_visual_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
//
|
||||
// Generate the basic runway outlines
|
||||
//
|
||||
|
||||
TGPolygon runway = gen_runway_w_mid( rwy_info, alt_m,
|
||||
2 * SG_FEET_TO_METER,
|
||||
2 * SG_FEET_TO_METER );
|
||||
|
||||
// runway half "a"
|
||||
TGPolygon runway_a;
|
||||
runway_a.erase();
|
||||
runway_a.add_node( 0, runway.get_pt(0, 0) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 1) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 2) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 5) );
|
||||
|
||||
// runway half "b"
|
||||
TGPolygon runway_b;
|
||||
runway_b.erase();
|
||||
runway_b.add_node( 0, runway.get_pt(0, 3) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 4) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 5) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 2) );
|
||||
|
||||
Point3D p;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (a half)");
|
||||
for ( j = 0; j < runway_a.contour_size( 0 ); ++j ) {
|
||||
p = runway_a.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (b half)");
|
||||
for ( j = 0; j < runway_b.contour_size( 0 ); ++j ) {
|
||||
p = runway_b.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
|
||||
//
|
||||
// Setup some variables and values to help us chop up the runway
|
||||
// into its various sections
|
||||
//
|
||||
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
// we add 2' to the length for texture overlap. This puts the
|
||||
// lines on the texture back to the edge of the runway where they
|
||||
// belong.
|
||||
double length = rwy_info.length / 2.0 + 2.0;
|
||||
if ( length < 1150 ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"This runway is not long enough for visual markings = "
|
||||
<< rwy_info.length );
|
||||
}
|
||||
|
||||
double start1_pct = 0.0;
|
||||
double start2_pct = 0.0;
|
||||
double end1_pct = 0.0;
|
||||
double end2_pct = 0.0;
|
||||
|
||||
//
|
||||
// Displaced threshold if it exists
|
||||
//
|
||||
|
||||
if ( rwy_info.disp_thresh1 > 0.0 ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Forward displaced threshold = "
|
||||
<< rwy_info.disp_thresh1 );
|
||||
|
||||
// reserve 90' for final arrows
|
||||
double thresh = rwy_info.disp_thresh1 - 90.0;
|
||||
|
||||
// number of full center arrows
|
||||
int count = (int)(thresh / 200.0);
|
||||
|
||||
// length of starting partial arrow
|
||||
double part_len = thresh - ( count * 200.0 );
|
||||
double tex_pct = (200.0 - part_len) / 200.0;
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, tex_pct, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// main chunks
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// final arrows
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "dspl_arrows",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
if ( rwy_info.disp_thresh2 > 0.0 ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Reverse displaced threshold = "
|
||||
<< rwy_info.disp_thresh2 );
|
||||
|
||||
// reserve 90' for final arrows
|
||||
double thresh = rwy_info.disp_thresh2 - 90.0;
|
||||
|
||||
// number of full center arrows
|
||||
int count = (int)(thresh / 200.0);
|
||||
|
||||
// length of starting partial arrow
|
||||
double part_len = thresh - ( count * 200.0 );
|
||||
double tex_pct = (200.0 - part_len) / 200.0;
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( part_len / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, tex_pct, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// main chunks
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_thresh",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
// final arrows
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "dspl_arrows",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Threshold
|
||||
//
|
||||
|
||||
// mini threshold
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 14 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 0.07,
|
||||
rwy_info.heading,
|
||||
material, "threshold",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
// starting (possibly partial chunk)
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 14 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 0.07,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "threshold",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
//
|
||||
// Runway designation letter
|
||||
//
|
||||
|
||||
int len = rwy_info.rwy_no.length();
|
||||
string letter = "";
|
||||
string rev_letter = "";
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
string tmp = rwy_info.rwy_no.substr(i, 1);
|
||||
if ( tmp == "L" ) {
|
||||
letter = "L";
|
||||
rev_letter = "R";
|
||||
} else if ( tmp == "R" ) {
|
||||
letter = "R";
|
||||
rev_letter = "L";
|
||||
} else if ( tmp == "C" ) {
|
||||
letter = "C";
|
||||
rev_letter = "C";
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway designation = " << rwy_info.rwy_no);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway designation letter = " << letter);
|
||||
|
||||
if ( !letter.empty() ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, rev_letter,
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 90.0 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, letter,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Runway designation number(s)
|
||||
//
|
||||
|
||||
len = rwy_info.rwy_no.length();
|
||||
string snum = rwy_info.rwy_no;
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
string tmp = rwy_info.rwy_no.substr(i, 1);
|
||||
if ( tmp == "L" || tmp == "R" || tmp == "C" || tmp == " " ) {
|
||||
snum = rwy_info.rwy_no.substr(0, i);
|
||||
}
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway num = '" << snum << "'");
|
||||
int num = atoi( snum.c_str() );
|
||||
while ( num <= 0 ) {
|
||||
num += 36;
|
||||
}
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 80.0 / length );
|
||||
gen_number_block( rwy_info, material, runway_b, rwy_info.heading + 180.0,
|
||||
num, start2_pct, end2_pct, rwy_polys, texparams, accum );
|
||||
|
||||
num += 18;
|
||||
while ( num > 36 ) {
|
||||
num -= 36;
|
||||
}
|
||||
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 80.0 / length );
|
||||
gen_number_block( rwy_info, material, runway_a, rwy_info.heading,
|
||||
num, start1_pct, end1_pct, rwy_polys, texparams, accum );
|
||||
|
||||
if ( false ) {
|
||||
//
|
||||
// Intermediate area before aiming point ...
|
||||
//
|
||||
|
||||
for ( i = 0; i < 3; ++i ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "centerline",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 200 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "centerline",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// Aiming point
|
||||
//
|
||||
|
||||
if ( end1_pct >= 1.0 ) {
|
||||
return;
|
||||
}
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "aim",
|
||||
rwy_polys, texparams, accum );
|
||||
|
||||
if ( end2_pct >= 1.0 ) {
|
||||
return;
|
||||
}
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + ( 400 / length );
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "aim",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
//
|
||||
// The rest ...
|
||||
//
|
||||
|
||||
// fit the 'rest' texture in as many times as will go evenly into
|
||||
// the remaining distance so we don't end up with a super short
|
||||
// section at the end.
|
||||
double ideal_rest_inc = ( 200.0 / length );
|
||||
int divs = (int)((1.0 - end1_pct) / ideal_rest_inc) + 1;
|
||||
double rest1_inc = (1.0 - end1_pct) / divs;
|
||||
|
||||
while ( end1_pct < 1.0 ) {
|
||||
start1_pct = end1_pct;
|
||||
end1_pct = start1_pct + rest1_inc;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "start1 = " << start1_pct << " end1 = " << end1_pct);
|
||||
|
||||
gen_runway_section( rwy_info, runway_a,
|
||||
start1_pct, end1_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
ideal_rest_inc = ( 200.0 / length );
|
||||
divs = (int)((1.0 - end2_pct) / ideal_rest_inc) + 1;
|
||||
double rest2_inc = (1.0 - end2_pct) / divs;
|
||||
|
||||
while ( end2_pct < 1.0 ) {
|
||||
start2_pct = end2_pct;
|
||||
end2_pct = start2_pct + rest2_inc;
|
||||
|
||||
gen_runway_section( rwy_info, runway_b,
|
||||
start2_pct, end2_pct,
|
||||
0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
rwy_info.heading + 180.0,
|
||||
material, "rest",
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
gen_runway_stopway( rwy_info, runway_a, runway_b,
|
||||
material,
|
||||
rwy_polys, texparams, accum );
|
||||
}
|
||||
|
||||
|
49
src/Airports/GenAirports850/rwy_visual.hxx
Normal file
49
src/Airports/GenAirports850/rwy_visual.hxx
Normal file
|
@ -0,0 +1,49 @@
|
|||
// rwy_visual.hxx -- Build a visual approach runway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: rwy_visual.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _RWY_VISUAL_HXX
|
||||
#define _RWY_VISUAL_HXX
|
||||
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "texparams.hxx"
|
||||
|
||||
|
||||
// generate a visual approach runway. The routine modifies rwy_polys,
|
||||
// texparams, and accum. For specific details and dimensions of
|
||||
// precision runway markings, please refer to FAA document AC
|
||||
// 150/5340-1H
|
||||
|
||||
void gen_visual_rwy( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const std::string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum );
|
||||
|
||||
|
||||
#endif // _RWY_VISUAL_HXX
|
151
src/Airports/GenAirports850/taxiway.cxx
Normal file
151
src/Airports/GenAirports850/taxiway.cxx
Normal file
|
@ -0,0 +1,151 @@
|
|||
// taxiway.cxx -- Build a taxiway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: taxiway.cxx,v 1.13 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "poly_extra.hxx"
|
||||
#include "rwy_common.hxx"
|
||||
#include "texparams.hxx"
|
||||
#include "taxiway.hxx"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
// generate a taxiway. The routine modifies rwy_polys, texparams, and
|
||||
// accum
|
||||
void gen_taxiway( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum )
|
||||
{
|
||||
int j, k;
|
||||
|
||||
TGPolygon runway = gen_runway_w_mid( rwy_info, alt_m, 0.0, 0.0 );
|
||||
|
||||
// runway half "a"
|
||||
TGPolygon runway_a;
|
||||
runway_a.erase();
|
||||
runway_a.add_node( 0, runway.get_pt(0, 0) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 1) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 2) );
|
||||
runway_a.add_node( 0, runway.get_pt(0, 5) );
|
||||
|
||||
// runway half "b"
|
||||
TGPolygon runway_b;
|
||||
runway_b.erase();
|
||||
runway_b.add_node( 0, runway.get_pt(0, 5) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 2) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 3) );
|
||||
runway_b.add_node( 0, runway.get_pt(0, 4) );
|
||||
|
||||
Point3D p;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (a half)");
|
||||
for ( j = 0; j < runway_a.contour_size( 0 ); ++j ) {
|
||||
p = runway_a.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (b half)");
|
||||
for ( j = 0; j < runway_b.contour_size( 0 ); ++j ) {
|
||||
p = runway_b.get_pt(0, j);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "len = " << rwy_info.length);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "width = " << rwy_info.width);
|
||||
|
||||
double twid;
|
||||
if ( rwy_info.width <= 150 ) {
|
||||
// narrower taxiways are more likely directional
|
||||
twid = rwy_info.width;
|
||||
} else {
|
||||
// wider taxiways are more likely large / non-directional
|
||||
// concrete areas
|
||||
twid = 250.0;
|
||||
}
|
||||
|
||||
TGPolygon clipped_a = tgPolygonDiff( runway_a, *accum );
|
||||
TGPolygon split_a = tgPolygonSplitLongEdges( clipped_a, 400.0 );
|
||||
sp.erase();
|
||||
|
||||
sp.set_poly( split_a );
|
||||
sp.set_material( material );
|
||||
sp.set_flag( "taxi" ); // mark as a taxiway
|
||||
rwy_polys->push_back( sp );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped_a = " << clipped_a.contours());
|
||||
*accum = tgPolygonUnion( runway_a, *accum );
|
||||
tp = TGTexParams( runway_a.get_pt(0,0),
|
||||
twid * SG_FEET_TO_METER,
|
||||
250 * SG_FEET_TO_METER,
|
||||
rwy_info.heading );
|
||||
texparams->push_back( tp );
|
||||
|
||||
TGPolygon clipped_b = tgPolygonDiff( runway_b, *accum );
|
||||
TGPolygon split_b = tgPolygonSplitLongEdges( clipped_b, 400.0 );
|
||||
sp.erase();
|
||||
sp.set_poly( split_b );
|
||||
sp.set_material( material );
|
||||
rwy_polys->push_back( sp );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped_b = " << clipped_b.contours());
|
||||
*accum = tgPolygonUnion( runway_b, *accum );
|
||||
tp = TGTexParams( runway_b.get_pt(0,0),
|
||||
twid * SG_FEET_TO_METER,
|
||||
250 * SG_FEET_TO_METER,
|
||||
rwy_info.heading + 180.0 );
|
||||
texparams->push_back( tp );
|
||||
|
||||
#if 0
|
||||
// after clip, but before removing T intersections
|
||||
char tmpa[256], tmpb[256];
|
||||
sprintf( tmpa, "a%d", i );
|
||||
sprintf( tmpb, "b%d", i );
|
||||
write_polygon( clipped_a, tmpa );
|
||||
write_polygon( clipped_b, tmpb );
|
||||
#endif
|
||||
|
||||
// print runway points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts (a)");
|
||||
for ( j = 0; j < clipped_a.contours(); ++j ) {
|
||||
for ( k = 0; k < clipped_a.contour_size( j ); ++k ) {
|
||||
p = clipped_a.get_pt(j, k);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
}
|
||||
|
||||
// print runway points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts (b)");
|
||||
for ( j = 0; j < clipped_b.contours(); ++j ) {
|
||||
for ( k = 0; k < clipped_b.contour_size( j ); ++k ) {
|
||||
p = clipped_b.get_pt(j, k);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
46
src/Airports/GenAirports850/taxiway.hxx
Normal file
46
src/Airports/GenAirports850/taxiway.hxx
Normal file
|
@ -0,0 +1,46 @@
|
|||
// taxiway.hxx -- Build a taxiway
|
||||
//
|
||||
// Written by Curtis Olson, started February 2002.
|
||||
//
|
||||
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: taxiway.hxx,v 1.5 2004-11-19 22:25:49 curt Exp $
|
||||
//
|
||||
|
||||
|
||||
#ifndef _TAXIWAY_HXX
|
||||
#define _TAXIWAY_HXX
|
||||
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "texparams.hxx"
|
||||
|
||||
|
||||
// generate a taxiway. The routine modifies rwy_polys, texparams, and
|
||||
// accum
|
||||
void gen_taxiway( const TGRunway& rwy_info,
|
||||
double alt_m,
|
||||
const std::string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
TGPolygon *accum );
|
||||
|
||||
|
||||
#endif // _TAXIWAY_HXX
|
100
src/Airports/GenAirports850/texparams.hxx
Normal file
100
src/Airports/GenAirports850/texparams.hxx
Normal file
|
@ -0,0 +1,100 @@
|
|||
// texparams.hxx -- A simple class to hold texture application
|
||||
// parameters for sections of the runway
|
||||
//
|
||||
// Written by Curtis Olson, started August 2000.
|
||||
//
|
||||
// Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: texparams.hxx,v 1.7 2004-11-19 22:25:49 curt Exp $
|
||||
|
||||
|
||||
#ifndef _TEXPARAMS_HXX
|
||||
#define _TEXPARAMS_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class TGTexParams {
|
||||
|
||||
private:
|
||||
|
||||
Point3D ref;
|
||||
double width;
|
||||
double length;
|
||||
double heading;
|
||||
|
||||
double minu;
|
||||
double maxu;
|
||||
double minv;
|
||||
double maxv;
|
||||
|
||||
public:
|
||||
|
||||
// Constructor and destructor
|
||||
inline TGTexParams( void ) { }
|
||||
inline TGTexParams( const Point3D &r, const double w, const double l,
|
||||
const double h ) {
|
||||
ref = r;
|
||||
width = w;
|
||||
length = l;
|
||||
heading = h;
|
||||
|
||||
minu = minv = 0.0;
|
||||
maxu = maxv = 1.0;
|
||||
}
|
||||
inline ~TGTexParams( void ) { }
|
||||
|
||||
inline Point3D get_ref() const { return ref; }
|
||||
inline void set_ref( const Point3D &r ) { ref = r; }
|
||||
|
||||
inline double get_width() const { return width; }
|
||||
inline void set_width( const double w ) { width = w; }
|
||||
|
||||
inline double get_length() const { return length; }
|
||||
inline void set_length( const double l ) { length = l; }
|
||||
|
||||
inline double get_heading() const { return heading; }
|
||||
inline void set_heading( const double h ) { heading = h; }
|
||||
|
||||
inline double get_minu() const { return minu; }
|
||||
inline void set_minu( const double x ) { minu = x; }
|
||||
|
||||
inline double get_maxu() const { return maxu; }
|
||||
inline void set_maxu( const double x ) { maxu = x; }
|
||||
|
||||
inline double get_minv() const { return minv; }
|
||||
inline void set_minv( const double x ) { minv = x; }
|
||||
|
||||
inline double get_maxv() const { return maxv; }
|
||||
inline void set_maxv( const double x ) { maxv = x; }
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector < TGTexParams > texparams_list;
|
||||
typedef texparams_list::iterator texparams_list_iterator;
|
||||
typedef texparams_list::const_iterator const_texparams_list_iterator;
|
||||
|
||||
|
||||
#endif // _TEXPARAMS_HXX
|
Loading…
Add table
Reference in a new issue