1
0
Fork 0

Refactor the runway code and exclude some math functions

from the class for general use
This commit is contained in:
Christian Schmitt 2011-10-06 14:22:00 +02:00
parent fdb37b36c7
commit 504f5ef46c
6 changed files with 345 additions and 288 deletions

View file

@ -1,5 +1,6 @@
add_executable(genapts850
airport.hxx airport.cxx
apt_math.hxx apt_math.cxx
apt_surface.hxx apt_surface.cxx
beznode.hxx
closedpoly.hxx closedpoly.cxx

View file

@ -0,0 +1,266 @@
// 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.
//
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <Geometry/poly_support.hxx>
#include "apt_math.hxx"
#include "global.hxx"
#include "poly_extra.hxx"
#include <stdlib.h>
using std::string;
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 a section of texture
void gen_tex_section( 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, double width, double length,
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 0.5m 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 = length / 2.0 + 0.5;
double sect_len = len * ( endl_pct - startl_pct );
// we add 0.5m 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 = width + 0.5;
double sect_wid = wid * ( endw_pct - startw_pct );
TGTexParams tp;
tp = TGTexParams( p0,
sect_wid,
sect_len,
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);
}
}
}

View file

@ -0,0 +1,29 @@
#ifndef _APT_MATH_HXX_
#define _APT_MATH_HXX_
#include <stdio.h>
#include <stdlib.h>
#include <Polygon/polygon.hxx>
#include <Polygon/superpoly.hxx>
#include <Geometry/point3d.hxx>
#include "texparams.hxx"
using std::string;
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 );
void gen_tex_section( 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, double width, double length,
const string& prefix,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum );
#endif

View file

@ -12,6 +12,7 @@
#include <Geometry/poly_support.hxx>
#include <Polygon/polygon.hxx>
#include "apt_math.hxx"
#include "beznode.hxx"
#include "runway.hxx"
@ -102,118 +103,6 @@ int Runway::BuildOsg ( osg::Group* airport )
return 0;
}
TGPolygon Runway::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 expansion specified in meters
// (return result points in degrees)
TGPolygon Runway::gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend )
{
TGPolygon result_list;
Point3D origin = GetMidpoint();
result_list = gen_wgs84_area( origin, rwy.length + 2.0*length_extend, displ1, displ2, rwy.width + 2.0*width_extend, rwy.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 Runway::gen_runway_w_mid( double alt_m, double length_extend_m, double width_extend_m )
{
TGPolygon result_list;
Point3D origin = GetMidpoint();
result_list = gen_wgs84_area( origin, rwy.length + 2.0*length_extend_m, 0.0, 0.0, rwy.width + 2.0 * width_extend_m, rwy.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;
}
int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
{

View file

@ -8,6 +8,7 @@
#include <Polygon/superpoly.hxx>
#include <Geometry/point3d.hxx>
#include "apt_math.hxx"
#include "texparams.hxx"
#include <osg/Group>
@ -17,6 +18,33 @@ using std::string;
class Runway
{
public:
Runway(char* def);
bool IsPrecision()
{
return true;
}
Point3D GetStart(void)
{
return ( Point3D( rwy.lon[0], rwy.lat[0], 0.0f ));
}
Point3D GetEnd(void)
{
return ( Point3D( rwy.lon[1], rwy.lat[1], 0.0f ));
}
Point3D GetMidpoint(void)
{
return ( Point3D( (rwy.lon[0]+rwy.lon[1])/2.0f, (rwy.lat[0]+rwy.lat[1])/2.0f, 0.0f) );
}
int BuildOsg( osg::Group* airport );
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
private:
struct TGRunway {
// data for whole runway
int surface;
@ -45,37 +73,20 @@ public:
TGRunway rwy;
Runway(char* def);
bool IsPrecision()
// Build Helpers:
// generate an area for a runway and include midpoints
TGPolygon gen_runway_w_mid( double alt_m, double length_extend_m, double width_extend_m )
{
return true;
return ( gen_wgs84_area(Point3D(GetMidpoint()), rwy.length + 2.0*length_extend_m, 0.0, 0.0, rwy.width + 2.0 * width_extend_m, rwy.heading, alt_m, true) );
}
Point3D GetStart(void)
// generate an area for a runway with expansion specified in meters
// (return result points in degrees)
TGPolygon gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend )
{
return ( Point3D( rwy.lon[0], rwy.lat[0], 0.0f ));
return ( gen_wgs84_area(Point3D(GetMidpoint()), rwy.length + 2.0*length_extend, displ1, displ2, rwy.width + 2.0*width_extend, rwy.heading, alt_m, false) );
}
Point3D GetEnd(void)
{
return ( Point3D( rwy.lon[1], rwy.lat[1], 0.0f ));
}
Point3D GetMidpoint(void)
{
return ( Point3D( (rwy.lon[0]+rwy.lon[1])/2.0f, (rwy.lat[0]+rwy.lat[1])/2.0f, 0.0f) );
}
int BuildOsg( osg::Group* airport );
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
private:
// Build Helpers
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 gen_runway_w_mid( double alt_m, double length_extend_m, double width_extend_m );
TGPolygon gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend );
void gen_number_block( const std::string& material,
TGPolygon poly, double heading, int num,

View file

@ -25,6 +25,7 @@
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include "apt_math.hxx"
#include "global.hxx"
#include "poly_extra.hxx"
#include "runway.hxx"
@ -138,8 +139,7 @@ void Runway::gen_runway_overrun( const TGPolygon& runway_half,
}
}
// generate a section of runway
// call the generic build function with runway-specific parameters
void Runway::gen_runway_section( const TGPolygon& runway,
double startl_pct, double endl_pct,
double startw_pct, double endw_pct,
@ -150,154 +150,15 @@ void Runway::gen_runway_section( const TGPolygon& runway,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum ) {
gen_tex_section( runway,
startl_pct, endl_pct,
startw_pct, endw_pct,
minu, maxu, minv, maxv,
heading, rwy.width, rwy.length,
prefix,
material,
rwy_polys,
texparams,
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 0.5m 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.length / 2.0 + 0.5;
double sect_len = len * ( endl_pct - startl_pct );
// we add 0.5m 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.width + 0.5;
double sect_wid = wid * ( endw_pct - startw_pct );
TGTexParams tp;
tp = TGTexParams( p0,
sect_wid,
sect_len,
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);
}
}
}