Adding initial genapts 850 support
This commit is contained in:
parent
324e6fc30f
commit
ef486df526
17 changed files with 5143 additions and 612 deletions
|
@ -1,20 +1,17 @@
|
|||
|
||||
|
||||
add_executable(genapts850
|
||||
apt_surface.hxx apt_surface.cxx
|
||||
build.cxx build.hxx
|
||||
airport.hxx airport.cxx
|
||||
apt_surface.hxx apt_surface.cxx
|
||||
beznode.hxx
|
||||
closedpoly.hxx closedpoly.cxx
|
||||
convex_hull.hxx convex_hull.cxx
|
||||
elevations.cxx elevations.hxx
|
||||
global.hxx
|
||||
heli_gen.cxx heli_gen.hxx
|
||||
lights.hxx lights.cxx
|
||||
main.cxx
|
||||
linearfeature.hxx linearfeature.cxx
|
||||
main.cxx
|
||||
parser.hxx parser.cxx
|
||||
point2d.cxx point2d.hxx
|
||||
poly_extra.cxx poly_extra.hxx
|
||||
runway.cxx runway.hxx
|
||||
rwy_common.cxx rwy_common.hxx
|
||||
rwy_gen.cxx rwy_gen.hxx
|
||||
rwy_simple.cxx rwy_simple.hxx
|
||||
taxiway.cxx taxiway.hxx
|
||||
runway.cxx runway.hxx
|
||||
texparams.hxx
|
||||
)
|
||||
|
||||
|
@ -25,6 +22,7 @@ target_link_libraries(genapts850
|
|||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GPC_LIBRARY}
|
||||
${NEWMAT_LIBRARY})
|
||||
${NEWMAT_LIBRARY}
|
||||
osg osgDB osgGA osgUtil osgViewer)
|
||||
|
||||
install(TARGETS genapts850 RUNTIME DESTINATION bin)
|
||||
|
|
2048
src/Airports/GenAirports850/airport.cxx
Normal file
2048
src/Airports/GenAirports850/airport.cxx
Normal file
File diff suppressed because it is too large
Load diff
49
src/Airports/GenAirports850/airport.hxx
Normal file
49
src/Airports/GenAirports850/airport.hxx
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef _AIRPORT_H_
|
||||
#define _AIRPORT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "runway.hxx"
|
||||
#include "closedpoly.hxx"
|
||||
#include "linearfeature.hxx"
|
||||
|
||||
using std::string;
|
||||
|
||||
class Airport
|
||||
{
|
||||
public:
|
||||
Airport( int c, char* def);
|
||||
|
||||
void AddRunway( Runway* runway )
|
||||
{
|
||||
runways.push_back( runway );
|
||||
}
|
||||
|
||||
void AddPavement( ClosedPoly* pavement )
|
||||
{
|
||||
pavements.push_back( pavement );
|
||||
}
|
||||
|
||||
void AddFeature( LinearFeature* feature )
|
||||
{
|
||||
features.push_back( feature );
|
||||
}
|
||||
|
||||
void BuildOsg( osg::Group* airport );
|
||||
void BuildBtg( const string& root, const string_list& elev_src );
|
||||
|
||||
private:
|
||||
int code; // airport, heliport or sea port
|
||||
int altitude; // in meters
|
||||
string icao; // airport code
|
||||
string description; // description
|
||||
|
||||
PavementList pavements;
|
||||
FeatureList features;
|
||||
RunwayList runways;
|
||||
};
|
||||
|
||||
typedef std::vector <Airport *> AirportList;
|
||||
|
||||
#endif
|
205
src/Airports/GenAirports850/beznode.hxx
Normal file
205
src/Airports/GenAirports850/beznode.hxx
Normal file
|
@ -0,0 +1,205 @@
|
|||
#ifndef _BEZNODE_H_
|
||||
#define _BEZNODE_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <osg/Vec3d>
|
||||
#include <Geometry/point3d.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
// TODO: where to put this
|
||||
inline osg::Vec3d SGPoint3DtoOSGVec3d( Point3D p )
|
||||
{
|
||||
return osg::Vec3d( p.x(), p.y(), p.z() );
|
||||
}
|
||||
|
||||
// TEMP...
|
||||
inline Point3D CalculateQuadraticLocation( Point3D p0, Point3D cp, Point3D p1, double t )
|
||||
{
|
||||
Point3D result;
|
||||
|
||||
double term1 = (1.0f - t) * (1.0f - t);
|
||||
double term2 = 2 * (1.0f - t) * t;
|
||||
double term3 = t * t;
|
||||
|
||||
result = (p0 * term1) + (cp * term2) + (p1 * term3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: Should be in a math library
|
||||
inline Point3D CalculateCubicLocation( Point3D p0, Point3D cp0, Point3D cp1, Point3D p1, double t )
|
||||
{
|
||||
Point3D result;
|
||||
|
||||
double term1 = (1.0f - t) * (1.0f - t) * (1.0f - t);
|
||||
double term2 = 3 * (1.0f - t) * (1.0f - t) * t;
|
||||
double term3 = 3 * (1.0f - t) * t * t;
|
||||
double term4 = t * t * t;
|
||||
|
||||
result = (p0 * term1) + (cp0 * term2) + (cp1 * term3) + (p1 * term4);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline double CalculateTheta( Point3D p0, Point3D p1, Point3D p2 )
|
||||
{
|
||||
Point3D u, v;
|
||||
double udist, vdist, uv_dot, tmp;
|
||||
|
||||
// u . v = ||u|| * ||v|| * cos(theta)
|
||||
|
||||
u = p1 - p0;
|
||||
udist = sqrt( u.x() * u.x() + u.y() * u.y() );
|
||||
// printf("udist = %.6f\n", udist);
|
||||
|
||||
v = p1 - p2;
|
||||
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);
|
||||
}
|
||||
|
||||
#define BEZIER_DETAIL (8)
|
||||
#define LINE_WIDTH (0.75)
|
||||
#define WIREFRAME (1)
|
||||
|
||||
#define CURVE_NONE (0)
|
||||
#define CURVE_LINEAR (1)
|
||||
#define CURVE_QUADRATIC (2)
|
||||
#define CURVE_CUBIC (3)
|
||||
|
||||
|
||||
class BezNode
|
||||
{
|
||||
public:
|
||||
BezNode( Point3D l ) : prev_cp(0.0f, 0.0f, 0.0f), next_cp(0.0f, 0.0f, 0.0f)
|
||||
{
|
||||
loc = l;
|
||||
mark = 0;
|
||||
light = 0;
|
||||
}
|
||||
|
||||
BezNode( double lat, double lon ) : prev_cp(0.0f, 0.0f, 0.0f), next_cp(0.0f, 0.0f, 0.0f)
|
||||
{
|
||||
loc = Point3D( lon, lat, 0.0f );
|
||||
mark = 0;
|
||||
light = 0;
|
||||
}
|
||||
|
||||
BezNode( Point3D l, Point3D cp )
|
||||
{
|
||||
loc = l;
|
||||
next_cp = cp;
|
||||
prev_cp = Mirror(cp);
|
||||
mark = 0;
|
||||
light = 0;
|
||||
}
|
||||
|
||||
BezNode( double lat, double lon, double cp_lat, double cp_lon )
|
||||
{
|
||||
loc = Point3D( lon, lat, 0.0f );
|
||||
next_cp = Point3D( cp_lon, cp_lat, 0.0f );
|
||||
prev_cp = Mirror( next_cp );
|
||||
mark = 0;
|
||||
light = 0;
|
||||
}
|
||||
|
||||
Point3D Mirror( Point3D pt )
|
||||
{
|
||||
// mirror given point about our location
|
||||
return (loc - (pt - loc));
|
||||
}
|
||||
|
||||
void SetMarking( int m )
|
||||
{
|
||||
mark = m;
|
||||
}
|
||||
|
||||
int GetMarking( )
|
||||
{
|
||||
return mark;
|
||||
}
|
||||
|
||||
void SetLighting( int l )
|
||||
{
|
||||
light = l;
|
||||
}
|
||||
|
||||
int GetLighting( )
|
||||
{
|
||||
return light;
|
||||
}
|
||||
|
||||
bool IsAt( double lat, double lon )
|
||||
{
|
||||
return ( (loc.lat() == lat) && (loc.lon() == lon) );
|
||||
}
|
||||
|
||||
bool HasPrevCp()
|
||||
{
|
||||
return ( (prev_cp.x() != 0.0f) && (prev_cp.y() != 0.0f) );
|
||||
}
|
||||
|
||||
bool HasNextCp()
|
||||
{
|
||||
return ( (next_cp.x() != 0.0f) && (next_cp.y() != 0.0f) );
|
||||
}
|
||||
|
||||
Point3D GetLoc()
|
||||
{
|
||||
return loc;
|
||||
}
|
||||
|
||||
Point3D GetPrevCp()
|
||||
{
|
||||
return prev_cp;
|
||||
}
|
||||
|
||||
Point3D GetNextCp()
|
||||
{
|
||||
return next_cp;
|
||||
}
|
||||
|
||||
void ClearNextCp(void)
|
||||
{
|
||||
next_cp = Point3D(0.0f,0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void SetNextCp( double lat, double lon )
|
||||
{
|
||||
next_cp = Point3D(lon, lat, 0.0f);
|
||||
}
|
||||
|
||||
// TODO: log levels and macros (does terragear have them?)
|
||||
void Print()
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG,
|
||||
"\tLoc(" << loc.x() << "," << loc.y() << ")" <<
|
||||
"\tprev_cp(" << prev_cp.x() << "," << prev_cp.y() << ")" <<
|
||||
"\tnext_cp(" << next_cp.x() << "," << next_cp.y() << ")" );
|
||||
}
|
||||
|
||||
private:
|
||||
Point3D loc;
|
||||
Point3D prev_cp;
|
||||
Point3D next_cp;
|
||||
int mark;
|
||||
int light;
|
||||
};
|
||||
|
||||
|
||||
// array of BezNodes make a contour
|
||||
typedef std::vector <BezNode *> BezContour;
|
||||
typedef std::vector <BezContour *> BezContourArray;
|
||||
|
||||
#endif
|
||||
|
656
src/Airports/GenAirports850/closedpoly.cxx
Normal file
656
src/Airports/GenAirports850/closedpoly.cxx
Normal file
|
@ -0,0 +1,656 @@
|
|||
#include <stdlib.h>
|
||||
#include <list>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osgUtil/Tessellator>
|
||||
|
||||
#include <Geometry/poly_support.hxx>
|
||||
|
||||
#include "beznode.hxx"
|
||||
#include "convex_hull.hxx"
|
||||
#include "closedpoly.hxx"
|
||||
|
||||
|
||||
ClosedPoly::ClosedPoly( int st, float s, float th, char* desc )
|
||||
{
|
||||
surface_type = st;
|
||||
smoothness = s;
|
||||
texture_heading = th;
|
||||
if ( desc )
|
||||
{
|
||||
strcpy( description, desc );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( description, "none" );
|
||||
}
|
||||
|
||||
boundary = NULL;
|
||||
cur_contour = NULL;
|
||||
cur_feat = NULL;
|
||||
cur_marking = 0;
|
||||
}
|
||||
|
||||
void ClosedPoly::AddNode( BezNode* node )
|
||||
{
|
||||
// if this is the first node of the contour - create a new contour
|
||||
if (!cur_contour)
|
||||
{
|
||||
cur_contour = new BezContour;
|
||||
}
|
||||
cur_contour->push_back( node );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "CLOSEDPOLY::ADDNODE : (" << node->GetLoc().x() << "," << node->GetLoc().y() << ")");
|
||||
// if recording a linear feature on the pavement, add this node
|
||||
// to it as well
|
||||
// TODO: just doing marking now, need lighting as well
|
||||
if (cur_feat)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " Adding node (" << node->GetLoc().x() << "," << node->GetLoc().y() << ") to current linear feature " << cur_marking);
|
||||
cur_feat->AddNode( node );
|
||||
|
||||
// if it should end, end it, and add to feature list
|
||||
if (cur_marking != node->GetMarking())
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " Node has marking " << node->GetMarking() << " end it");
|
||||
features.push_back( cur_feat );
|
||||
cur_feat = NULL;
|
||||
cur_marking = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// should we start a new feature here?
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " Node has marking " << node->GetMarking() << " cur marking is " << cur_marking);
|
||||
if ( (cur_marking == 0) && (node->GetMarking()))
|
||||
{
|
||||
// Yes - create a new linear feature
|
||||
// TODO: With offset, as all pavement markings should be
|
||||
// a bit in from the edge
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " Starting a new linear feature");
|
||||
cur_feat = new LinearFeature(NULL);
|
||||
cur_feat->AddNode( node );
|
||||
cur_marking = node->GetMarking();
|
||||
}
|
||||
}
|
||||
|
||||
void ClosedPoly::CreateConvexHull( void )
|
||||
{
|
||||
TGPolygon convexHull;
|
||||
point_list nodes;
|
||||
Point3D p;
|
||||
int i;
|
||||
|
||||
for (i=0; i<boundary->size(); i++)
|
||||
{
|
||||
p = boundary->at(i)->GetLoc();
|
||||
nodes.push_back( p );
|
||||
}
|
||||
|
||||
convexHull = convex_hull( nodes );
|
||||
hull = convexHull.get_contour(0);
|
||||
}
|
||||
|
||||
int ClosedPoly::CloseCurContour()
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Close Contour");
|
||||
|
||||
// if we are recording a pavement marking - it must be closed -
|
||||
// add the first node of the poly
|
||||
if (cur_feat)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "We still have an active linear feature - add the first node to close it");
|
||||
|
||||
cur_feat->AddNode( cur_contour->at(0) );
|
||||
|
||||
features.push_back( cur_feat );
|
||||
cur_feat = NULL;
|
||||
cur_marking = 0;
|
||||
}
|
||||
|
||||
// add the contour to the poly - first one is the outer boundary
|
||||
// subsequent contours are holes
|
||||
if ( boundary == NULL )
|
||||
{
|
||||
boundary = cur_contour;
|
||||
|
||||
// generate the convex hull from the bezcontour node locations
|
||||
CreateConvexHull();
|
||||
|
||||
cur_contour = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
holes.push_back( cur_contour );
|
||||
cur_contour = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ClosedPoly::ConvertContour( BezContour* src, point_list *dst, bool reverse )
|
||||
{
|
||||
BezNode* prevNode;
|
||||
BezNode* curNode;
|
||||
BezNode* nextNode;
|
||||
|
||||
Point3D prevLoc;
|
||||
Point3D curLoc;
|
||||
Point3D nextLoc;
|
||||
Point3D cp1;
|
||||
Point3D cp2;
|
||||
|
||||
int start, end, inc;
|
||||
|
||||
int curve_type = CURVE_LINEAR;
|
||||
int i;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating a contour with " << src->size() << " nodes");
|
||||
|
||||
// clear anything in this point list
|
||||
dst->empty();
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
start = src->size()-1;
|
||||
end = -1;
|
||||
inc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = 0;
|
||||
end = src->size();
|
||||
inc = 1;
|
||||
}
|
||||
|
||||
// iterate through each bezier node in the contour
|
||||
for (i=0; i <= src->size()-1; i++)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\nHandling Node " << i << "\n\n");
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// set prev node to last in the contour, as all contours must be closed
|
||||
prevNode = src->at( src->size()-1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, it's just the previous index
|
||||
prevNode = src->at( i-1 );
|
||||
}
|
||||
|
||||
curNode = src->at(i);
|
||||
|
||||
if (i < src->size() - 1)
|
||||
{
|
||||
nextNode = src->at(i+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// for the last node, next is the first. as all contours are closed
|
||||
nextNode = src->at(0);
|
||||
}
|
||||
|
||||
// determine the type of curve from prev (just to get correct prev location)
|
||||
// once we start drawing the curve from cur to next, we can just remember the prev loc
|
||||
if (prevNode->HasNextCp())
|
||||
{
|
||||
// curve from prev is cubic or quadratic
|
||||
if(curNode->HasPrevCp())
|
||||
{
|
||||
// curve from prev is cubic : calculate the last location on the curve
|
||||
prevLoc = CalculateCubicLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve from prev is quadratic : use prev node next cp
|
||||
prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve from prev is quadratic or linear
|
||||
if( curNode->HasPrevCp() )
|
||||
{
|
||||
// curve from prev is quadratic : calculate the last location on the curve
|
||||
prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve from prev is linear : just use prev node location
|
||||
prevLoc = prevNode->GetLoc();
|
||||
}
|
||||
}
|
||||
|
||||
// now determine how we will iterate from current node to next node
|
||||
if( curNode->HasNextCp() )
|
||||
{
|
||||
// next curve is cubic or quadratic
|
||||
if( nextNode->HasPrevCp() )
|
||||
{
|
||||
// curve is cubic : need both control points
|
||||
curve_type = CURVE_CUBIC;
|
||||
cp1 = curNode->GetNextCp();
|
||||
cp2 = nextNode->GetPrevCp();
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve is quadratic using current nodes cp as the cp
|
||||
curve_type = CURVE_QUADRATIC;
|
||||
cp1 = curNode->GetNextCp();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// next curve is quadratic or linear
|
||||
if( nextNode->HasPrevCp() )
|
||||
{
|
||||
// curve is quadratic using next nodes cp as the cp
|
||||
curve_type = CURVE_QUADRATIC;
|
||||
cp1 = nextNode->GetPrevCp();
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve is linear
|
||||
curve_type = CURVE_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize current location
|
||||
curLoc = curNode->GetLoc();
|
||||
if (curve_type != CURVE_LINEAR)
|
||||
{
|
||||
for (int p=0; p<BEZIER_DETAIL; p++)
|
||||
{
|
||||
// calculate next location
|
||||
if (curve_type == CURVE_QUADRATIC)
|
||||
{
|
||||
nextLoc = CalculateQuadraticLocation( curNode->GetLoc(), cp1, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
nextLoc = CalculateCubicLocation( curNode->GetLoc(), cp1, cp2, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) );
|
||||
}
|
||||
|
||||
// add the pavement vertex
|
||||
// convert from lat/lon to geo
|
||||
// (maybe later) - check some simgear objects...
|
||||
dst->push_back( curLoc );
|
||||
if (p==0)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "adding Curve Anchor node (type " << curve_type << ") at (" << curLoc.x() << "," << curLoc.y() << ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " add bezier node (type " << curve_type << ") at (" << curLoc.x() << "," << curLoc.y() << ")");
|
||||
}
|
||||
|
||||
// now set set prev and cur locations for the next iteration
|
||||
prevLoc = curLoc;
|
||||
curLoc = nextLoc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nextLoc = nextNode->GetLoc();
|
||||
|
||||
// just add the one vertex - linear
|
||||
dst->push_back( curLoc );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "adding Linear Anchor node at (" << curLoc.x() << "," << curLoc.y() << ")");
|
||||
}
|
||||
}
|
||||
|
||||
// Add the first point again?
|
||||
// dst->push_back( src->at(0)->GetLoc() );
|
||||
}
|
||||
|
||||
void ExpandPoint( Point3D *prev, Point3D *cur, Point3D *next, double expand_by, double *heading, double *offset )
|
||||
{
|
||||
int turn_direction;
|
||||
bool reverse_dir = false;
|
||||
double offset_dir;
|
||||
double next_dir;
|
||||
double az1, az2;
|
||||
double dist;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Find average angle for contour: prev (" << *prev << "), "
|
||||
"cur (" << *cur << "), "
|
||||
"next (" << *next << ")" );
|
||||
|
||||
// first, find if the line turns left or right ar src
|
||||
// for this, take the cross product of the vectors from prev to src, and src to next.
|
||||
// if the cross product is negetive, we've turned to the left
|
||||
// if the cross product is positive, we've turned to the right
|
||||
// if the cross product is 0, then we need to use the direction passed in
|
||||
SGVec3d dir1 = prev->toSGVec3d() - cur->toSGVec3d();
|
||||
dir1 = normalize(dir1);
|
||||
|
||||
SGVec3d dir2 = next->toSGVec3d() - cur->toSGVec3d();
|
||||
dir2 = normalize(dir2);
|
||||
|
||||
// Now find the average
|
||||
SGVec3d avg = dir1 + dir2;
|
||||
avg = normalize(avg);
|
||||
|
||||
// find the offset angle
|
||||
geo_inverse_wgs_84( avg.y(), avg.x(), 0.0f, 0.0f, &offset_dir, &az2, &dist);
|
||||
|
||||
// find the direction to the next point
|
||||
geo_inverse_wgs_84( cur->y(), cur->x(), next->y(), next->x(), &next_dir, &az2, &dist);
|
||||
|
||||
// calculate correct distance for the offset point
|
||||
*offset = (expand_by)/sin(SGMiscd::deg2rad(offset_dir-next_dir));
|
||||
*heading = offset_dir;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "heading is " << *heading << " distance is " << *offset );
|
||||
}
|
||||
|
||||
void ClosedPoly::ExpandContour( point_list& src, TGPolygon& dst, double dist )
|
||||
{
|
||||
point_list expanded_boundary;
|
||||
Point3D prevPoint, curPoint, nextPoint;
|
||||
double theta;
|
||||
double expand_by;
|
||||
double expanded_x, expanded_y;
|
||||
Point3D expanded_point;
|
||||
|
||||
double h1, h2, h3;
|
||||
double o1, o2, o3;
|
||||
double az2;
|
||||
int i;
|
||||
|
||||
// iterate through each bezier node in the contour
|
||||
for (i=0; i<src.size(); i++)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\nExpanding point " << i << "\n\n");
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// set prev node to last in the contour, as all contours must be closed
|
||||
prevPoint = src.at( src.size()-1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, it's just the last index
|
||||
prevPoint = src.at( i-1 );
|
||||
}
|
||||
|
||||
curPoint = src.at(i);
|
||||
|
||||
if (i<src.size()-1)
|
||||
{
|
||||
nextPoint = src.at(i+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// for the last node, next is the first. as all contours are closed
|
||||
nextPoint = src.at(0);
|
||||
}
|
||||
|
||||
// calculate the angle between cur->prev and cur->next
|
||||
theta = SGMiscd::rad2deg(CalculateTheta(prevPoint, curPoint, nextPoint));
|
||||
|
||||
if ( theta < 90.0 )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\nClosed POLY case 1 (theta < 90) " << description << ": theta is " << theta );
|
||||
|
||||
// calculate the expanded point heading and offset from current point
|
||||
ExpandPoint( &prevPoint, &curPoint, &nextPoint, dist, &h1, &o1 );
|
||||
|
||||
if (o1 > dist*2.0)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\ntheta is " << theta << " distance is " << o1 << " CLAMPING to " << dist*2 );
|
||||
o1 = dist*2;
|
||||
|
||||
if (o1 > 100)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\nClosed POLY " << description << ": theta is " << theta << " distance is " << o1 << " WHAT HAPPENED " );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
geo_direct_wgs_84( curPoint.y(), curPoint.x(), h1, o1, &expanded_y, &expanded_x, &az2 );
|
||||
expanded_point = Point3D( expanded_x, expanded_y, 0.0f );
|
||||
expanded_boundary.push_back( expanded_point );
|
||||
}
|
||||
else if ( abs(theta - 180.0) < 0.1 )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\nClosed POLY case 2 (theta close to 180) " << description << ": theta is " << theta );
|
||||
|
||||
// calculate the expanded point heading and offset from current point
|
||||
ExpandPoint( &prevPoint, &curPoint, &nextPoint, dist, &h1, &o1 );
|
||||
|
||||
// straight line blows up math - dist should be exactly as given
|
||||
o1 = dist;
|
||||
|
||||
geo_direct_wgs_84( curPoint.y(), curPoint.x(), h1, o1, &expanded_y, &expanded_x, &az2 );
|
||||
expanded_point = Point3D( expanded_x, expanded_y, 0.0f );
|
||||
expanded_boundary.push_back( expanded_point );
|
||||
}
|
||||
else
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\nClosed POLY case 3 (fall through) " << description << ": theta is " << theta );
|
||||
|
||||
// calculate the expanded point heading and offset from current point
|
||||
ExpandPoint( &prevPoint, &curPoint, &nextPoint, dist, &h1, &o1 );
|
||||
|
||||
if (o1 > dist*2)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "\ntheta is " << theta << " distance is " << o1 << " WHAT HAPPENED " );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
geo_direct_wgs_84( curPoint.y(), curPoint.x(), h1, o1, &expanded_y, &expanded_x, &az2 );
|
||||
expanded_point = Point3D( expanded_x, expanded_y, 0.0f );
|
||||
expanded_boundary.push_back( expanded_point );
|
||||
}
|
||||
}
|
||||
|
||||
dst.add_contour( expanded_boundary, 9 );
|
||||
}
|
||||
|
||||
osg::DrawArrays* ClosedPoly::CreateOsgPrimitive( point_list contour, osg::Vec3Array* vpave )
|
||||
{
|
||||
int i;
|
||||
Point3D p;
|
||||
osg::DrawArrays* primitive;
|
||||
int start_vert = vpave->size();
|
||||
|
||||
for (i=0; i<contour.size(); i++)
|
||||
{
|
||||
p = contour[i];
|
||||
vpave->push_back( osg::Vec3d(p.x(), p.y(), 0.0) );
|
||||
}
|
||||
|
||||
primitive = new osg::DrawArrays(osg::PrimitiveSet::POLYGON, start_vert, vpave->size()-start_vert);
|
||||
|
||||
return primitive;
|
||||
}
|
||||
|
||||
// finish the poly - convert to TGPolygon, and tesselate
|
||||
int ClosedPoly::Finish()
|
||||
{
|
||||
BezContour* src_contour;
|
||||
point_list dst_contour;
|
||||
BezNode* node;
|
||||
|
||||
// error handling
|
||||
if (boundary == NULL)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "no boundary");
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Converting a poly with " << holes.size() << " holes");
|
||||
|
||||
if (boundary != NULL)
|
||||
{
|
||||
// create the boundary
|
||||
ConvertContour( boundary, &dst_contour, false );
|
||||
|
||||
// and add it to the geometry
|
||||
pre_tess.add_contour( dst_contour, 0 );
|
||||
|
||||
// The convert the hole contours
|
||||
for (int i=0; i<holes.size(); i++)
|
||||
{
|
||||
dst_contour.clear();
|
||||
ConvertContour( holes[i], &dst_contour, false );
|
||||
pre_tess.add_contour( dst_contour, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// save memory by deleting unneeded resources
|
||||
delete boundary;
|
||||
boundary = NULL;
|
||||
|
||||
// The convert the hole contours
|
||||
holes.clear();
|
||||
}
|
||||
|
||||
int ClosedPoly::BuildOsg( osg::Group* airport )
|
||||
{
|
||||
BezContour* contour;
|
||||
BezNode* node;
|
||||
osg::Geode* geode_pave; // has the stateset, and geometry for this poly
|
||||
osg::Geometry* pavement;
|
||||
osg::StateSet* ss_pave; // just a simple stateset for now
|
||||
osg::PolygonMode* polymode;
|
||||
osg::Vec4Array* col_pave; // just grey for now...
|
||||
osg::Vec3Array* v_pave; // ALL verticies (boundary and holes)
|
||||
osg::DrawArrays* primitive; // an index array for boundary / hole
|
||||
int num_verts; // number of verticies in a contour
|
||||
int i; // ?
|
||||
|
||||
if ( pre_tess.contours() )
|
||||
{
|
||||
// Setup a polygonmode for wireframe debuging
|
||||
polymode = new osg::PolygonMode;
|
||||
polymode->setMode( osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE );
|
||||
|
||||
// Create a drawable for the pavement poly (boundary and holes)
|
||||
pavement = new osg::Geometry;
|
||||
|
||||
// make pavement grey : do this when reading the poly
|
||||
col_pave = new osg::Vec4Array;
|
||||
col_pave->push_back(osg::Vec4(0.5f,0.5f,0.5f,1.0f));
|
||||
pavement->setColorArray(col_pave);
|
||||
pavement->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
// set up pavement stateset
|
||||
geode_pave = new osg::Geode();
|
||||
ss_pave = new osg::StateSet();
|
||||
|
||||
#if WIREFRAME
|
||||
ss_pave->setAttribute( polymode );
|
||||
#endif
|
||||
geode_pave->setStateSet(ss_pave);
|
||||
|
||||
v_pave = new osg::Vec3Array;
|
||||
pavement->setVertexArray(v_pave);
|
||||
|
||||
// create the boundary
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " Adding pavement boundary");
|
||||
primitive = CreateOsgPrimitive( pre_tess.get_contour( 0 ), v_pave );
|
||||
if (hull.size() > 0)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " boundary has " << hull.size() << "verts" );
|
||||
}
|
||||
|
||||
// add the hole contours
|
||||
for (i=1; i<pre_tess.contours(); i++)
|
||||
{
|
||||
primitive = CreateOsgPrimitive( pre_tess.get_contour( i ), v_pave );
|
||||
pavement->addPrimitiveSet(primitive);
|
||||
}
|
||||
|
||||
osgUtil::Tessellator *tess = new osgUtil::Tessellator;
|
||||
tess->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
|
||||
tess->retessellatePolygons(*pavement);
|
||||
|
||||
geode_pave->addDrawable(pavement);
|
||||
airport->addChild(geode_pave);
|
||||
|
||||
#if 0 // debug ExpandPoly
|
||||
TGPolygon base;
|
||||
ExpandPoly( hull, base, 20 );
|
||||
primitive = CreateOsgPrimitive( base.get_contour( 0 ), v_pave );
|
||||
pavement->addPrimitiveSet(primitive);
|
||||
#endif
|
||||
|
||||
geode_pave->addDrawable(pavement);
|
||||
airport->addChild(geode_pave);
|
||||
|
||||
// add the pavement markings
|
||||
#if 0
|
||||
printf("ClosedPoly::Finish - Finish %d linear features\n", features.size());
|
||||
for (int feat=0; feat<features.size(); feat++)
|
||||
{
|
||||
features.at(feat)->Finish(airport);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
|
||||
{
|
||||
TGPolygon base, safe_base;
|
||||
string material;
|
||||
int j, k;
|
||||
|
||||
material = "pa_tiedown";
|
||||
|
||||
// verify the poly has been generated
|
||||
if ( pre_tess.contours() )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours");
|
||||
|
||||
// do this before clipping and generating the base
|
||||
pre_tess = remove_dups( pre_tess );
|
||||
pre_tess = reduce_degeneracy( pre_tess );
|
||||
|
||||
for (int c=0; c<pre_tess.contours(); c++)
|
||||
{
|
||||
for (int pt=0; pt<pre_tess.contour_size(c); pt++)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: contour " << c << " pt " << pt << ": (" << pre_tess.get_pt(c, pt).x() << "," << pre_tess.get_pt(c, pt).y() << ")" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
TGPolygon clipped = tgPolygonDiff( pre_tess, *accum );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: clipped poly has " << clipped.contours() << " contours");
|
||||
|
||||
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: split poly has " << split.contours() << " contours");
|
||||
|
||||
|
||||
sp.erase();
|
||||
sp.set_poly( split );
|
||||
sp.set_material( material );
|
||||
rwy_polys->push_back( sp );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours());
|
||||
*accum = tgPolygonUnion( pre_tess, *accum );
|
||||
tp = TGTexParams( pre_tess.get_pt(0,0), 20.0 /* TODO poly width */, 20.0 /* TODO poly length */, texture_heading );
|
||||
texparams->push_back( tp );
|
||||
|
||||
ExpandContour( hull, base, 20.0 );
|
||||
ExpandContour( hull, safe_base, 50.0 );
|
||||
|
||||
// add this to the airport clearing
|
||||
*apt_clearing = tgPolygonUnion( safe_base, *apt_clearing);
|
||||
|
||||
// and add the clearing to the base
|
||||
*apt_base = tgPolygonUnion( base, *apt_base );
|
||||
}
|
||||
|
||||
// clean up to save ram : we're done here...
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
66
src/Airports/GenAirports850/closedpoly.hxx
Normal file
66
src/Airports/GenAirports850/closedpoly.hxx
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef _BEZPOLY_H_
|
||||
#define _BEZPOLY_H_
|
||||
|
||||
#include "beznode.hxx"
|
||||
#include "linearfeature.hxx"
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
#include <Geometry/point3d.hxx>
|
||||
|
||||
#include "texparams.hxx"
|
||||
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
using std::string;
|
||||
|
||||
class ClosedPoly
|
||||
{
|
||||
public:
|
||||
ClosedPoly( int st, float s, float th, char* desc );
|
||||
|
||||
void AddNode( BezNode* node );
|
||||
int CloseCurContour();
|
||||
int Finish();
|
||||
int BuildOsg( osg::Group* airport );
|
||||
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
|
||||
|
||||
private:
|
||||
//osg::DrawArrays* CreatePrimitive( BezContour* contour, osg::Vec3Array* v_pave );
|
||||
// convert the BezierPoly to a normal Poly (adding nodes for the curves)
|
||||
void CreateConvexHull( void );
|
||||
void ConvertContour( BezContour* src, point_list *dst, bool reverse );
|
||||
osg::DrawArrays* CreateOsgPrimitive( point_list contour, osg::Vec3Array* vpave );
|
||||
void ExpandContour( point_list& src, TGPolygon& dst, double dist );
|
||||
|
||||
int surface_type;
|
||||
float smoothness;
|
||||
float texture_heading;
|
||||
char description[64];
|
||||
|
||||
// outer boundary definition as bezier nodes
|
||||
BezContour* boundary;
|
||||
|
||||
// holes
|
||||
BezContourArray holes;
|
||||
|
||||
// contour that nodes will be added until done
|
||||
BezContour* cur_contour;
|
||||
|
||||
|
||||
// outer boundary as convex hull
|
||||
point_list hull;
|
||||
|
||||
// Converted polygon after parsing complete
|
||||
TGPolygon pre_tess;
|
||||
|
||||
// pavement definitions can have multiple linear features (markings)
|
||||
LinearFeature* cur_feat;
|
||||
FeatureList features;
|
||||
int cur_marking;
|
||||
};
|
||||
|
||||
typedef std::vector <ClosedPoly *> PavementList;
|
||||
|
||||
#endif
|
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
|
||||
|
||||
|
|
@ -145,7 +145,6 @@ double tgAverageElevation( const string &root, const string_list elev_src,
|
|||
|
||||
// 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 )
|
||||
{
|
||||
|
@ -252,7 +251,6 @@ void tgCalcElevations( const string &root, const string_list elev_src,
|
|||
<< grid_average);
|
||||
}
|
||||
|
||||
|
||||
// clamp all elevations to the specified range
|
||||
|
||||
void tgClampElevations( SimpleMatrix &Pts,
|
||||
|
|
|
@ -48,9 +48,7 @@ double tgAverageElevation( const string &root, const string_list elev_src,
|
|||
|
||||
// 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 );
|
||||
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 );
|
||||
void tgClampElevations( SimpleMatrix &Pts, double center_m, double max_clamp_m );
|
||||
|
|
550
src/Airports/GenAirports850/linearfeature.cxx
Normal file
550
src/Airports/GenAirports850/linearfeature.cxx
Normal file
|
@ -0,0 +1,550 @@
|
|||
#include "beznode.hxx"
|
||||
#include "linearfeature.hxx"
|
||||
#include "math.h"
|
||||
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/math/SGVec3.hxx>
|
||||
#include <simgear/math/SGMisc.hxx>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/PolygonOffset>
|
||||
|
||||
int LinearFeature::Finish( osg::Group* airport )
|
||||
{
|
||||
BezNode* node;
|
||||
int i, j;
|
||||
int prev_dir = 0;
|
||||
double direction;
|
||||
double dist1, dist2;
|
||||
|
||||
printf("Finish a %s Linear Feature with %d verticies\n", closed ? "closed" : "open", contour.size());
|
||||
|
||||
BezNode* prevNode;
|
||||
BezNode* curNode;
|
||||
BezNode* nextNode;
|
||||
|
||||
Point3D prevLoc;
|
||||
Point3D curLoc;
|
||||
Point3D nextLoc;
|
||||
|
||||
Point3D st_cur1;
|
||||
Point3D st_cur2;
|
||||
double st_curx, st_cury, az2;
|
||||
|
||||
// create a DrawElement for the stripe triangle strip
|
||||
int stripe_idx = 0;
|
||||
int cur_marking = 0;
|
||||
|
||||
osg::Vec3dArray* v_stripe = new osg::Vec3dArray;
|
||||
|
||||
for (i=0; i<contour.size(); i++)
|
||||
{
|
||||
printf("\nHandling Node %d\n\n", i );
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// if closed, set prev node to last in the contour
|
||||
if (closed)
|
||||
{
|
||||
prevNode = contour.at( contour.size()-1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
prevNode = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prevNode = contour.at( i-1 );
|
||||
}
|
||||
|
||||
curNode = contour.at(i);
|
||||
|
||||
if (i<contour.size()-1)
|
||||
{
|
||||
nextNode = contour.at(i+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if closed, set next node to the first in the contour
|
||||
if (closed)
|
||||
{
|
||||
nextNode = contour.at(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextNode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// determine the type of curve from prev (just to get correct prev location)
|
||||
// once we start drawing the curve from cur to next, we can just remember the prev loc
|
||||
if (prevNode)
|
||||
{
|
||||
if (prevNode->HasNextCp())
|
||||
{
|
||||
// curve from prev is cubic or quadratic
|
||||
if(curNode->HasPrevCp())
|
||||
{
|
||||
// curve from prev is cubic : calculate the last location on the curve
|
||||
prevLoc = CalculateCubicLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve from prev is quadratic : use prev node next cp
|
||||
prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve from prev is quadratic or linear
|
||||
if( curNode->HasPrevCp() )
|
||||
{
|
||||
// curve from prev is quadratic : calculate the last location on the curve
|
||||
prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve from prev is linear : just use prev node location
|
||||
prevLoc = prevNode->GetLoc();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prevLoc = Point3D(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
int curve_type = CURVE_LINEAR;
|
||||
Point3D cp1;
|
||||
Point3D cp2;
|
||||
|
||||
if ( nextNode)
|
||||
{
|
||||
// now determine how we will iterate through cur node to next node
|
||||
if( curNode->HasNextCp() )
|
||||
{
|
||||
// next curve is cubic or quadratic
|
||||
if( nextNode->HasPrevCp() )
|
||||
{
|
||||
// curve is cubic : need both control points
|
||||
curve_type = CURVE_CUBIC;
|
||||
cp1 = curNode->GetNextCp();
|
||||
cp2 = nextNode->GetPrevCp();
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve is quadratic using current nodes cp as the cp
|
||||
curve_type = CURVE_QUADRATIC;
|
||||
cp1 = curNode->GetNextCp();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// next curve is quadratic or linear
|
||||
if( nextNode->HasPrevCp() )
|
||||
{
|
||||
// curve is quadratic using next nodes cp as the cp
|
||||
curve_type = CURVE_QUADRATIC;
|
||||
cp1 = nextNode->GetPrevCp();
|
||||
}
|
||||
else
|
||||
{
|
||||
// curve is linear
|
||||
curve_type = CURVE_LINEAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
curve_type = CURVE_NONE;
|
||||
}
|
||||
|
||||
// initialize current location
|
||||
curLoc = curNode->GetLoc();
|
||||
switch( curve_type )
|
||||
{
|
||||
case CURVE_QUADRATIC:
|
||||
case CURVE_CUBIC:
|
||||
for (int p=0; p<BEZIER_DETAIL; p++)
|
||||
{
|
||||
// calculate next location
|
||||
if (curve_type == CURVE_QUADRATIC)
|
||||
{
|
||||
nextLoc = CalculateQuadraticLocation( curNode->GetLoc(), cp1, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
nextLoc = CalculateCubicLocation( curNode->GetLoc(), cp1, cp2, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) );
|
||||
}
|
||||
|
||||
// set the verticies
|
||||
// convert from lat/lon to geodisc
|
||||
// (maybe later) - check some simgear objects...
|
||||
// printf("Added vertex at %lf,%lf\n",
|
||||
// add the pavement vertex
|
||||
if (p==0)
|
||||
{
|
||||
printf("adding Curve Anchor node (type %d) at (%lf,%lf)\n", curve_type, curLoc.x(), curLoc.y());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" add bezier node (type %d) at (%lf,%lf)\n", curve_type, curLoc.x(), curLoc.y());
|
||||
}
|
||||
|
||||
// find the average direction at this vertex...
|
||||
direction = CalcMarkingVerticies( &prevLoc, &curLoc, &nextLoc, -1, &prev_dir, &dist1, &dist2 );
|
||||
|
||||
printf("got dir for bezier : prev_dir %d, dist1 %lf, dist2 %lf\n", prev_dir, dist1, dist2);
|
||||
|
||||
// distance can't be constant - it's the hypotenous of a right triangler with a constant offset from the outer rim.
|
||||
geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist1, &st_curx, &st_cury, &az2 );
|
||||
st_cur1 = Point3D( st_curx, st_cury, 0.0f );
|
||||
v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur1) );
|
||||
|
||||
geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist2, &st_curx, &st_cury, &az2 );
|
||||
st_cur2 = Point3D( st_curx, st_cury, 0.0f );
|
||||
v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur2) );
|
||||
|
||||
printf("node at (%lf,%lf) has stripe verticies (%lf,%lf) and (%lf,%lf)\n",
|
||||
curLoc.x(), curLoc.y(),
|
||||
st_cur1.x(), st_cur1.y(),
|
||||
st_cur2.x(), st_cur2.y()
|
||||
);
|
||||
|
||||
// now set set prev and cur locations for the next iteration
|
||||
prevLoc = curLoc;
|
||||
curLoc = nextLoc;
|
||||
}
|
||||
break;
|
||||
|
||||
case CURVE_LINEAR:
|
||||
nextLoc = nextNode->GetLoc();
|
||||
|
||||
printf("adding Linear Anchor node at (%lf,%lf)\n", curLoc.x(), curLoc.y());
|
||||
|
||||
// find the average direction at this vertex...
|
||||
direction = CalcMarkingVerticies( &prevLoc, &curLoc, &nextLoc, -1, &prev_dir, &dist1, &dist2 );
|
||||
|
||||
printf("got dir for linear : prev_dir %d, dist1 %lf, dist2 %lf\n", prev_dir, dist1, dist2);
|
||||
|
||||
// distance can't be constant - it's the hypotenous of a right triangler with a constant offset from the outer rim.
|
||||
printf("calc direct: curLoc is (%lf,%lf), direction is %lf, dist is %lf\n", curLoc.x(), curLoc.y(), direction, dist1);
|
||||
|
||||
geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist1, &st_curx, &st_cury, &az2 );
|
||||
st_cur1 = Point3D( st_curx, st_cury, 0.0f );
|
||||
|
||||
v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur1) );
|
||||
|
||||
geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist2, &st_curx, &st_cury, &az2 );
|
||||
st_cur2 = Point3D( st_curx, st_cury, 0.0f );
|
||||
v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur2) );
|
||||
|
||||
printf("node at (%lf,%lf) has stripe verticies (%lf,%lf) and (%lf,%lf)\n",
|
||||
curLoc.x(), curLoc.y(),
|
||||
st_cur1.x(), st_cur1.y(),
|
||||
st_cur2.x(), st_cur2.y()
|
||||
);
|
||||
break;
|
||||
|
||||
case CURVE_NONE:
|
||||
nextLoc = Point3D(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// we need to add the last verticies based on cur and prev position.
|
||||
// find the average direction at this vertex...
|
||||
direction = CalcMarkingVerticies( &prevLoc, &curLoc, &nextLoc, -1, &prev_dir, &dist1, &dist2 );
|
||||
|
||||
printf("got dir for term points : prev_dir %lf, dist1 %lf, dist2 %lf\n", prev_dir, dist1, dist2);
|
||||
|
||||
// distance can't be constant - it's the hypotenous of a right triangler with a constant offset from the outer rim.
|
||||
geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist1, &st_curx, &st_cury, &az2 );
|
||||
st_cur1 = Point3D( st_curx, st_cury, 0.0f );
|
||||
v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur1) );
|
||||
|
||||
geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist2, &st_curx, &st_cury, &az2 );
|
||||
st_cur2 = Point3D( st_curx, st_cury, 0.0f );
|
||||
v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur2) );
|
||||
|
||||
printf("node at (%lf,%lf) has stripe verticies (%lf,%lf) and (%lf,%lf)\n",
|
||||
curLoc.x(), curLoc.y(),
|
||||
st_cur1.x(), st_cur1.y(),
|
||||
st_cur2.x(), st_cur2.y()
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("End feature %d \n", v_stripe->size() );
|
||||
airport->addChild(FinishMarking( v_stripe ) );
|
||||
}
|
||||
|
||||
int LinearFeature::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
|
||||
{
|
||||
string material;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// this should be in the class
|
||||
// TODO: Should Be AddMidMarkingVerticies - and handle offset (used in LinearFeature::Finish only)
|
||||
double CalcMiddleMarkingVerticies( Point3D *prev, Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 )
|
||||
{
|
||||
int turn_direction;
|
||||
bool reverse_dir = false;
|
||||
double offset_dir;
|
||||
double next_dir;
|
||||
double az1, az2;
|
||||
double dist;
|
||||
|
||||
printf("Find averate angle for mark: prev (%lf,%lf), cur(%lf,%lf), next(%lf,%lf)\n", prev->x(), prev->y(), cur->x(), cur->y(), next->x(), next->y());
|
||||
|
||||
// first, find if the line turns left or right ar src
|
||||
// for this, take the cross product of the vectors from prev to src, and src to next.
|
||||
// if the cross product is negetive, we've turned to the left
|
||||
// if the cross product is positive, we've turned to the right
|
||||
// if the cross product is 0, then we need to use the direction passed in
|
||||
SGVec3d dir1 = cur->toSGVec3d() - prev->toSGVec3d();
|
||||
dir1 = normalize(dir1);
|
||||
|
||||
printf("normalized dir1 is (%lf,%lf)\n", dir1.x(), dir1.y());
|
||||
|
||||
SGVec3d dir2 = next->toSGVec3d() - cur->toSGVec3d();
|
||||
dir2 = normalize(dir2);
|
||||
|
||||
printf("normalized dir2 is (%lf,%lf)\n", dir2.x(), dir2.y());
|
||||
|
||||
SGVec3d cp = cross(dir1,dir2);
|
||||
if (cp.z() < 0.0)
|
||||
{
|
||||
turn_direction = -1;
|
||||
}
|
||||
else if (cp.z() > 0.0)
|
||||
{
|
||||
turn_direction = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
turn_direction = 0;
|
||||
}
|
||||
|
||||
printf("turn direction is %d\n", turn_direction);
|
||||
|
||||
// Now find the average
|
||||
SGVec3d avg = -dir1 + dir2;
|
||||
|
||||
printf("avg is (%lf,%lf)\n", avg.x(), avg.y());
|
||||
|
||||
// now determine which way the direction needs to point
|
||||
if ((wind == -1) && (turn_direction == 1))
|
||||
{
|
||||
reverse_dir = true;
|
||||
}
|
||||
if ((wind == 1) && (turn_direction == -1))
|
||||
{
|
||||
reverse_dir = true;
|
||||
}
|
||||
|
||||
printf("reverse dir is %d\n", reverse_dir);
|
||||
|
||||
// find the offset angle
|
||||
geo_inverse_wgs_84( 0.0f, 0.0f, avg.x(), avg.y(), &offset_dir, &az2, &dist);
|
||||
if (reverse_dir)
|
||||
{
|
||||
offset_dir += 180;
|
||||
while (offset_dir >= 360.0)
|
||||
{
|
||||
offset_dir -= 360.0;
|
||||
}
|
||||
}
|
||||
printf("offset direction is %lf\n", offset_dir);
|
||||
|
||||
// find the direction to the next point
|
||||
geo_inverse_wgs_84( cur->x(), cur->y(), next->x(), next->y(), &next_dir, &az2, &dist);
|
||||
printf("next direction is %lf\n", next_dir);
|
||||
|
||||
// calculate correct distance for the offset point
|
||||
*dist1 = (-LINE_WIDTH)/sin(SGMiscd::deg2rad(next_dir-offset_dir));
|
||||
*dist2 = (LINE_WIDTH)/sin(SGMiscd::deg2rad(next_dir-offset_dir));
|
||||
|
||||
return offset_dir;
|
||||
}
|
||||
|
||||
// TODO: Should Be AddStartMarkingVerticies - and handle offset (used in LinearFeature::Finish only)
|
||||
double CalcStartMarkingVerticies( Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 )
|
||||
{
|
||||
double offset_dir;
|
||||
double az1, az2;
|
||||
double dist;
|
||||
|
||||
printf("Find start angle for mark: cur(%lf,%lf), next(%lf,%lf)\n", cur->x(), cur->y(), next->x(), next->y());
|
||||
|
||||
// find the offset angle
|
||||
geo_inverse_wgs_84( cur->x(), cur->y(), next->x(), next->y(), &offset_dir, &az2, &dist);
|
||||
offset_dir -= 90;
|
||||
if (offset_dir < 0)
|
||||
{
|
||||
offset_dir += 360;
|
||||
}
|
||||
|
||||
printf("offset direction is %lf\n", offset_dir);
|
||||
|
||||
// calculate correct distance for the offset point
|
||||
*dist1 = (-LINE_WIDTH);
|
||||
*dist2 = (LINE_WIDTH);
|
||||
|
||||
return offset_dir;
|
||||
}
|
||||
|
||||
// TODO: Should Be AddEndMarkingVerticies - and handle offset (used in LinearFeature::Finish only)
|
||||
double CalcEndMarkingVerticies( Point3D *prev, Point3D *cur, int wind, int *prev_dir, double *dist1, double *dist2 )
|
||||
{
|
||||
double offset_dir;
|
||||
double az1, az2;
|
||||
double dist;
|
||||
|
||||
printf("Find end angle for mark: prev(%lf,%lf), cur(%lf,%lf)\n", prev->x(), prev->y(), cur->x(), cur->y());
|
||||
|
||||
// find the offset angle
|
||||
geo_inverse_wgs_84( prev->x(), prev->y(), cur->x(), cur->y(), &offset_dir, &az2, &dist);
|
||||
offset_dir -= 90;
|
||||
if (offset_dir < 0)
|
||||
{
|
||||
offset_dir += 360;
|
||||
}
|
||||
|
||||
printf("offset direction is %lf\n", offset_dir);
|
||||
|
||||
// calculate correct distance for the offset point
|
||||
*dist1 = (-LINE_WIDTH);
|
||||
*dist2 = (LINE_WIDTH);
|
||||
|
||||
return offset_dir;
|
||||
}
|
||||
|
||||
// TODO: Should Be AddMarkingVerticies - and handle offset (used in LinearFeature::Finish only)
|
||||
double CalcMarkingVerticies( Point3D *prev, Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 )
|
||||
{
|
||||
double offset_dir;
|
||||
|
||||
// first, we need to see if we want to average the directions (we have both prev, and next)
|
||||
if ( (prev->x() == 0.0f) && (prev->y() == 0.0f) )
|
||||
{
|
||||
// direction is 90 degrees less than from current to next
|
||||
offset_dir = CalcStartMarkingVerticies( cur, next, wind, prev_dir, dist1, dist2 );
|
||||
printf("got dist 1: %lf, dist2: %lf\n", *dist1, *dist2);
|
||||
}
|
||||
else if ( (next->x() == 0.0f) && (next->y() == 0.0f) )
|
||||
{
|
||||
// direction is 90 degrees less than from current to next
|
||||
offset_dir = CalcEndMarkingVerticies( prev, cur, wind, prev_dir, dist1, dist2 );
|
||||
printf("got dist 1: %lf, dist2: %lf\n", *dist1, *dist2);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset_dir = CalcMiddleMarkingVerticies( prev, cur, next, wind, prev_dir, dist1, dist2 );
|
||||
printf("got dist 1: %lf, dist2: %lf\n", *dist1, *dist2);
|
||||
}
|
||||
|
||||
printf("return from CalcMarkingVerticies: dirst1: %lf, dist2: %lf\n", *dist1, *dist2);
|
||||
|
||||
return offset_dir;
|
||||
}
|
||||
|
||||
// need to refactor this stuff.
|
||||
osg::Geode* FinishMarking( osg::Vec3dArray* verticies )
|
||||
{
|
||||
osg::Geometry* stripe = NULL;
|
||||
osg::Geode* geode_stripe = NULL;
|
||||
osg::StateSet* ss_stripe = NULL;
|
||||
osg::PolygonMode* polymode = NULL;
|
||||
osg::Vec4Array* col_stripe = NULL;
|
||||
int j;
|
||||
|
||||
// set up polygon offset
|
||||
osg::PolygonOffset* polyoffset = new osg::PolygonOffset;
|
||||
polyoffset->setFactor(-1.00f);
|
||||
polyoffset->setUnits(-1.00f);
|
||||
|
||||
polymode = new osg::PolygonMode;
|
||||
polymode->setMode( osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE );
|
||||
|
||||
col_stripe = new osg::Vec4Array;
|
||||
col_stripe->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
|
||||
|
||||
// Create a new stripe geometry
|
||||
stripe = new osg::Geometry;
|
||||
stripe->setColorArray(col_stripe);
|
||||
stripe->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
ss_stripe = new osg::StateSet();
|
||||
ss_stripe->setAttributeAndModes(polyoffset,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
|
||||
#if WIREFRAME
|
||||
ss_stripe->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
|
||||
#endif
|
||||
geode_stripe = new osg::Geode();
|
||||
geode_stripe->setStateSet(ss_stripe);
|
||||
|
||||
stripe->setVertexArray(verticies);
|
||||
|
||||
// create the index array for the stripe
|
||||
osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_TRIANGLE_STRIP,verticies->size()));
|
||||
|
||||
for (j=0; j<verticies->size(); j++)
|
||||
{
|
||||
drawElements[j] = j;
|
||||
}
|
||||
|
||||
for (int k=0; k<j; k++)
|
||||
{
|
||||
printf("index %d is %d\n", k, drawElements[k]);
|
||||
}
|
||||
|
||||
stripe->addPrimitiveSet(&drawElements);
|
||||
|
||||
geode_stripe->addDrawable(stripe);
|
||||
|
||||
return geode_stripe;
|
||||
}
|
||||
|
||||
// TODO: Add this into Linear Feature
|
||||
osg::Vec3dArray* StartMarking()
|
||||
{
|
||||
osg::Vec3dArray* v_marking = new osg::Vec3dArray;
|
||||
|
||||
return v_marking;
|
||||
}
|
||||
|
||||
// TODO: move this into LinearFeature
|
||||
osg::Vec3dArray* CheckMarking(int cur_marking, int new_marking, osg::Vec3dArray* v_marking, osg::Group* airport)
|
||||
{
|
||||
// check if we need to finish a marking
|
||||
printf("Check Marking : current is %d, new is %d\n", cur_marking, new_marking);
|
||||
|
||||
if ( (v_marking != NULL) && (cur_marking != new_marking) )
|
||||
{
|
||||
printf("End current marking %d and start new marking %d : mark poly has %d verticies\n", cur_marking, new_marking, v_marking->size() );
|
||||
for (int k=0; k<v_marking->size(); k++)
|
||||
{
|
||||
printf("vertex %d is (%lf, %lf)\n", k, v_marking->at(k).x(), v_marking->at(k).y());
|
||||
}
|
||||
|
||||
// END THE CURRENT MARKING
|
||||
airport->addChild(FinishMarking( v_marking ) );
|
||||
v_marking = NULL;
|
||||
}
|
||||
|
||||
// Start recording a new marking
|
||||
if ( (v_marking == NULL) && (new_marking != 0) )
|
||||
{
|
||||
// start a new marking
|
||||
printf("Start new marking %d\n", new_marking);
|
||||
|
||||
v_marking = StartMarking();
|
||||
}
|
||||
|
||||
return v_marking;
|
||||
}
|
67
src/Airports/GenAirports850/linearfeature.hxx
Normal file
67
src/Airports/GenAirports850/linearfeature.hxx
Normal file
|
@ -0,0 +1,67 @@
|
|||
#ifndef _LINEARFEATURE_H_
|
||||
#define _LINEARFEATURE_H_
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
#include <Geometry/point3d.hxx>
|
||||
|
||||
#include "texparams.hxx"
|
||||
|
||||
#include <osg/Group>
|
||||
|
||||
using std::string;
|
||||
|
||||
class LinearFeature
|
||||
{
|
||||
public:
|
||||
LinearFeature( char* desc )
|
||||
{
|
||||
if ( desc )
|
||||
{
|
||||
strcpy( description, desc );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( description, "none" );
|
||||
}
|
||||
|
||||
offset = 0.0f;
|
||||
closed = false;
|
||||
}
|
||||
|
||||
void AddNode( BezNode* b )
|
||||
{
|
||||
contour.push_back( b );
|
||||
}
|
||||
|
||||
void SetClosed()
|
||||
{
|
||||
closed = true;
|
||||
}
|
||||
|
||||
int Finish( osg::Group* airport );
|
||||
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
|
||||
|
||||
private:
|
||||
char description[256];
|
||||
|
||||
// contour definition
|
||||
BezContour contour;
|
||||
|
||||
// TODO : Implement offset
|
||||
double offset;
|
||||
|
||||
bool closed;
|
||||
};
|
||||
|
||||
typedef std::vector <LinearFeature *> FeatureList;
|
||||
|
||||
// add this to the class
|
||||
extern double CalcMarkingVerticies( Point3D *prev, Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 );
|
||||
|
||||
// don't know what to do with these
|
||||
extern osg::Geode* FinishMarking( osg::Vec3dArray* verticies );
|
||||
extern osg::Vec3dArray* CheckMarking(int cur_marking, int new_marking, osg::Vec3dArray* v_marking, osg::Group* airport);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,67 +1,85 @@
|
|||
// 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 $
|
||||
//
|
||||
/* OpenSceneGraph example, osgshaderterrain.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Depth>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/GL2Extensions>
|
||||
#include <osg/Material>
|
||||
#include <osg/Math>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osg/Program>
|
||||
#include <osg/Projection>
|
||||
#include <osg/Shader>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Switch>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Uniform>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/FileUtils>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <osgUtil/Tessellator>
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
#include <osgText/Text>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/TerrainManipulator>
|
||||
#include <osgGA/StateSetManipulator>
|
||||
|
||||
#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/sg_path.hxx>
|
||||
|
||||
#include <simgear/misc/sgstream.hxx>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
//#include <simgear/misc/strutils.hxx>
|
||||
|
||||
#include <Polygon/index.hxx>
|
||||
#include <Geometry/util.hxx>
|
||||
|
||||
#include "build.hxx"
|
||||
#include "beznode.hxx"
|
||||
#include "closedpoly.hxx"
|
||||
#include "linearfeature.hxx"
|
||||
#include "parser.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 );
|
||||
// TODO : Modularize this function
|
||||
// IDEAS
|
||||
// 1) Start / Stop MarkStyle
|
||||
// 2) Start / Stop LightStyle
|
||||
// 3) holes
|
||||
// 4) CreatePavementSS(pavement type)
|
||||
// 5) CreateMarkingSS(marking type)
|
||||
// 6) CalcStripeOffsets should be AddMarkingVerticies, and take the 2 distances from pavement edge...
|
||||
// SCRAP ALL IDEAS - Markings are encapsulated in LinearFeature class.
|
||||
// Start creates a new object
|
||||
// End closes the object (and should add it to a list - either in the parser, or ClosedPoly)
|
||||
|
||||
// Display usage
|
||||
static void usage( int argc, char **argv ) {
|
||||
|
@ -73,6 +91,7 @@ static void usage( int argc, char **argv ) {
|
|||
<< "[ --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" );
|
||||
|
@ -86,58 +105,29 @@ void setup_default_elevation_sources(string_list& elev_src) {
|
|||
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 );
|
||||
}
|
||||
|
||||
// TODO: where do these belong
|
||||
int nudge = 10;
|
||||
double slope_max = 0.2;
|
||||
|
||||
// reads the apt_full file and extracts and processes the individual
|
||||
// airport records
|
||||
int main( int argc, char **argv ) {
|
||||
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;
|
||||
bool ready_to_go = true;
|
||||
bool view_osg = false;
|
||||
|
||||
string_list elev_src;
|
||||
elev_src.clear();
|
||||
setup_default_elevation_sources(elev_src);
|
||||
|
||||
sglog().setLogLevels( SG_GENERAL, SG_INFO );
|
||||
// Set verbose
|
||||
sglog().setLogLevels( SG_GENERAL, SG_BULK );
|
||||
// sglog().setLogLevels( SG_GENERAL, SG_INFO );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Run genapt");
|
||||
|
||||
// parse arguments
|
||||
string work_dir = "";
|
||||
|
@ -145,63 +135,109 @@ int main( int argc, char **argv ) {
|
|||
string start_id = "";
|
||||
string airport_id = "";
|
||||
int arg_pos;
|
||||
for (arg_pos = 1; arg_pos < argc; arg_pos++) {
|
||||
|
||||
for (arg_pos = 1; arg_pos < argc; arg_pos++)
|
||||
{
|
||||
string arg = argv[arg_pos];
|
||||
if ( arg.find("--work=") == 0 ) {
|
||||
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 ) {
|
||||
}
|
||||
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);
|
||||
}
|
||||
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() );
|
||||
}
|
||||
#if 0
|
||||
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 ) {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
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("--view") == 0 )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Found --view : view OSG model" );
|
||||
view_osg = true;
|
||||
}
|
||||
else if ( (arg.find("--max-slope=") == 0) )
|
||||
{
|
||||
slope_max = atof( arg.substr(12).c_str() );
|
||||
}
|
||||
#if 0
|
||||
else if ( (arg.find("--help") == 0) || (arg.find("-h") == 0) )
|
||||
{
|
||||
help( argc, argv, elev_src );
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
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 ) {
|
||||
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);
|
||||
|
@ -210,26 +246,29 @@ int main( int argc, char **argv ) {
|
|||
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) {
|
||||
min_lat < -90 || max_lat > 90 ||
|
||||
min_lon < -180 || max_lon > 180)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Bad longitude or latitude");
|
||||
exit(1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( work_dir == "" ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Error: no work directory specified." );
|
||||
usage( argc, argv );
|
||||
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);
|
||||
if ( input_file == "" )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Error: no input file." );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// make work directory
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Creating airportarea directory");
|
||||
|
||||
string airportareadir=work_dir+"/AirportArea";
|
||||
SGPath sgp( airportareadir );
|
||||
sgp.append( "dummy" );
|
||||
|
@ -242,264 +281,60 @@ int main( int argc, char **argv ) {
|
|||
poly_index_init( counter_file );
|
||||
|
||||
sg_gzifstream in( input_file );
|
||||
if ( !in.is_open() ) {
|
||||
if ( !in.is_open() )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << input_file );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
string_list runways_list;
|
||||
string_list water_rw_list;
|
||||
string_list beacon_list;
|
||||
string_list tower_list;
|
||||
string_list windsock_list;
|
||||
string_list light_list;
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Creating parser");
|
||||
|
||||
vector<string> token;
|
||||
string last_apt_id = "";
|
||||
string last_apt_info = "";
|
||||
string last_apt_type = "";
|
||||
string line;
|
||||
char tmp[2048];
|
||||
// Create the parser...
|
||||
Parser* parser = new Parser(input_file);
|
||||
|
||||
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();
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Parse katl");
|
||||
parser->Parse((char*)"katl");
|
||||
|
||||
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.)
|
||||
if (view_osg)
|
||||
{
|
||||
// just view in OSG
|
||||
osg::Group* airportNode;
|
||||
|
||||
// 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 */ ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "View OSG");
|
||||
airportNode = parser->CreateOsgGroup();
|
||||
|
||||
// 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 );
|
||||
// construct the viewer.
|
||||
osgViewer::Viewer viewer;
|
||||
|
||||
if ( !last_apt_id.empty()) {
|
||||
if ( runways_list.size() ) {
|
||||
vector<string> rwy_token
|
||||
= simgear::strutils::split( runways_list[0] );
|
||||
if ( token[0] == "100" ){
|
||||
rwy = token[8];
|
||||
lat = atof( token[9].c_str() );
|
||||
lon = atof( token[10].c_str() );
|
||||
}
|
||||
// add the thread model handler
|
||||
viewer.addEventHandler(new osgViewer::ThreadingHandler);
|
||||
|
||||
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;
|
||||
}
|
||||
// add the window size toggle handler
|
||||
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
|
||||
|
||||
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 );
|
||||
// add model to viewer.
|
||||
viewer.setSceneData( airportNode );
|
||||
viewer.setUpViewAcrossAllScreens();
|
||||
|
||||
// process previous record
|
||||
// process_airport(last_apt_id, runways_list, argv[2]);
|
||||
try {
|
||||
if ( last_apt_type == "16" /* Seaplane base */ ) {
|
||||
// skip building 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,
|
||||
water_rw_list,
|
||||
beacon_list,
|
||||
tower_list,
|
||||
windsock_list,
|
||||
light_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
// create the windows and run the threads.
|
||||
viewer.realize();
|
||||
|
||||
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
|
||||
|
||||
last_apt_id = id;
|
||||
last_apt_info = line;
|
||||
last_apt_type = token[0];
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(airportNode);
|
||||
|
||||
// clear runway list for start of next airport
|
||||
runways_list.clear();
|
||||
water_rw_list.clear();
|
||||
beacon_list.clear();
|
||||
tower_list.clear();
|
||||
windsock_list.clear();
|
||||
light_list.clear();
|
||||
} else if ( token[0] == "100" || token[0] == "102") {
|
||||
// runway entry (Land or heli)
|
||||
runways_list.push_back(line);
|
||||
} else if ( token[0] == "101" ) {
|
||||
// Water runway. Here we don't have to create any textures.
|
||||
// Only place some buoys
|
||||
water_rw_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" ) {
|
||||
// PAPI / VASI list
|
||||
light_list.push_back(line);
|
||||
} 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 if ( token[0] >= "110" ) {
|
||||
//ignore taxiways for now
|
||||
} else if ( token[0] == "10" ) {
|
||||
//ignore old taxiways for now
|
||||
} else {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Unknown line in file: " << line );
|
||||
exit(-1);
|
||||
}
|
||||
viewer.run();
|
||||
}
|
||||
else
|
||||
{
|
||||
// write a .btg file....
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Write BTG");
|
||||
parser->WriteBtg(work_dir, elev_src);
|
||||
}
|
||||
|
||||
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 */ ) {
|
||||
// skip building 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,
|
||||
water_rw_list,
|
||||
beacon_list,
|
||||
tower_list,
|
||||
windsock_list,
|
||||
light_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]");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Done");
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
451
src/Airports/GenAirports850/parser.cxx
Normal file
451
src/Airports/GenAirports850/parser.cxx
Normal file
|
@ -0,0 +1,451 @@
|
|||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/misc/sgstream.hxx>
|
||||
|
||||
#include "parser.hxx"
|
||||
|
||||
#if 0
|
||||
int Parser::ParseBoundry(char* line)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int Parser::Parse( char* icao )
|
||||
{
|
||||
string line;
|
||||
char tmp[2048];
|
||||
|
||||
sg_gzifstream in( filename );
|
||||
if ( !in.is_open() )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << filename );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while ( !in.eof() )
|
||||
{
|
||||
in.getline(tmp, 2048);
|
||||
line = tmp;
|
||||
|
||||
// Parse the line
|
||||
ParseLine(tmp);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BezNode* Parser::ParseNode( int type, char* line, BezNode* prevNode )
|
||||
{
|
||||
double lat, lon;
|
||||
double ctrl_lat, ctrl_lon;
|
||||
int mark_type, light_type;
|
||||
BezNode *curNode = NULL;
|
||||
|
||||
bool hasCtrl;
|
||||
bool close;
|
||||
bool term;
|
||||
bool hasMarking = false;
|
||||
bool hasLighting = false;
|
||||
int numParams;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case NODE_CODE:
|
||||
hasCtrl = false;
|
||||
close = false;
|
||||
term = false;
|
||||
break;
|
||||
|
||||
case BEZIER_NODE_CODE:
|
||||
hasCtrl = true;
|
||||
close = false;
|
||||
term = false;
|
||||
break;
|
||||
|
||||
case CLOSE_NODE_CODE:
|
||||
hasCtrl = false;
|
||||
close = true;
|
||||
term = false;
|
||||
break;
|
||||
|
||||
case CLOSE_BEZIER_NODE_CODE:
|
||||
hasCtrl = true;
|
||||
close = true;
|
||||
term = false;
|
||||
break;
|
||||
|
||||
case TERM_NODE_CODE:
|
||||
hasCtrl = false;
|
||||
close = false;
|
||||
term = true;
|
||||
break;
|
||||
|
||||
case TERM_BEZIER_NODE_CODE:
|
||||
hasCtrl = true;
|
||||
close = false;
|
||||
term = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// parse the line
|
||||
if (hasCtrl)
|
||||
{
|
||||
numParams = sscanf(line, "%lf %lf %lf %lf %d %d", &lat, &lon, &ctrl_lat, &ctrl_lon, &mark_type, &light_type);
|
||||
if (numParams > 4)
|
||||
{
|
||||
hasMarking = true;
|
||||
}
|
||||
if (numParams > 5)
|
||||
{
|
||||
hasLighting = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numParams = sscanf(line, "%lf %lf %d %d", &lat, &lon, &mark_type, &light_type);
|
||||
if (numParams > 2)
|
||||
{
|
||||
hasMarking = true;
|
||||
}
|
||||
if (numParams > 3)
|
||||
{
|
||||
hasLighting = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (prevNode) && (prevNode->IsAt( lat, lon )) )
|
||||
{
|
||||
curNode = prevNode;
|
||||
|
||||
// editing already existent node
|
||||
if (hasCtrl)
|
||||
{
|
||||
// we have ctrl info -> set it
|
||||
curNode->SetNextCp(ctrl_lat,ctrl_lon);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no control info - make sure we clear anything in next
|
||||
curNode->ClearNextCp();
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a new node, add it - as first part never has prev cp
|
||||
if (curNode == NULL)
|
||||
{
|
||||
if (hasCtrl)
|
||||
{
|
||||
curNode = new BezNode(lat, lon, ctrl_lat, ctrl_lon);
|
||||
}
|
||||
else
|
||||
{
|
||||
curNode = new BezNode(lat, lon);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasMarking)
|
||||
{
|
||||
curNode->SetMarking( mark_type );
|
||||
}
|
||||
|
||||
if (hasLighting)
|
||||
{
|
||||
curNode->SetLighting( light_type );
|
||||
}
|
||||
|
||||
return curNode;
|
||||
}
|
||||
|
||||
LinearFeature* Parser::ParseFeature( char* line )
|
||||
{
|
||||
LinearFeature* feature;
|
||||
|
||||
if (strlen( line ))
|
||||
{
|
||||
feature = new LinearFeature(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
feature = new LinearFeature(NULL);
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Linear Feature with desription \"" << line << "\"");
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
ClosedPoly* Parser::ParsePavement( char* line )
|
||||
{
|
||||
ClosedPoly* poly;
|
||||
int st = 0;
|
||||
float s = 0.0f;
|
||||
float th = 0.0f;
|
||||
char desc[256];
|
||||
char *d = NULL;
|
||||
int numParams;
|
||||
|
||||
numParams = sscanf(line, "%d %f %f %ls", &st, &s, &th, desc);
|
||||
|
||||
if (numParams == 4)
|
||||
{
|
||||
d = strstr(line,desc);
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Closed Poly with st " << st << " smoothness " << s << " thexture heading " << th << " and description " << d);
|
||||
poly = new ClosedPoly(st, s, th, d);
|
||||
|
||||
return poly;
|
||||
}
|
||||
|
||||
int Parser::SetState( int state )
|
||||
{
|
||||
// if we are currently parsing pavement, the oly way we know we are done
|
||||
// is when we get a non-node line to parse
|
||||
if ( cur_airport && cur_state == STATE_PARSE_PAVEMENT )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Closing and Adding pavement");
|
||||
cur_pavement->Finish();
|
||||
cur_airport->AddPavement( cur_pavement );
|
||||
cur_pavement = NULL;
|
||||
}
|
||||
|
||||
cur_state = state;
|
||||
}
|
||||
|
||||
// TODO: This should be a loop here, and main should just pass the file name and airport code...
|
||||
int Parser::ParseLine(char* line)
|
||||
{
|
||||
char* tok;
|
||||
int code;
|
||||
|
||||
BezNode* cur_node = NULL;
|
||||
|
||||
// Get the number code
|
||||
tok = strtok(line, " \t\r\n");
|
||||
|
||||
if (tok)
|
||||
{
|
||||
line += strlen(tok)+1;
|
||||
code = atoi(tok);
|
||||
|
||||
switch(code)
|
||||
{
|
||||
case LAND_AIRPORT_CODE:
|
||||
case SEA_AIRPORT_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing land airport: " << line);
|
||||
cur_airport = new Airport( code, line );
|
||||
airports.push_back( cur_airport );
|
||||
break;
|
||||
case HELIPORT_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing heliport: " << line);
|
||||
break;
|
||||
|
||||
case LAND_RUNWAY_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing runway: " << line);
|
||||
cur_runway = new Runway(line);
|
||||
if (cur_airport)
|
||||
{
|
||||
cur_airport->AddRunway( cur_runway );
|
||||
}
|
||||
break;
|
||||
|
||||
case WATER_RUNWAY_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing water runway: " << line);
|
||||
break;
|
||||
case HELIPAD_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing helipad: " << line);
|
||||
break;
|
||||
|
||||
case PAVEMENT_CODE:
|
||||
SetState( STATE_PARSE_PAVEMENT );
|
||||
cur_pavement = ParsePavement( line );
|
||||
break;
|
||||
|
||||
case LINEAR_FEATURE_CODE:
|
||||
SetState( STATE_PARSE_FEATURE );
|
||||
cur_feat = ParseFeature( line );
|
||||
break;
|
||||
|
||||
case BOUNDRY_CODE:
|
||||
SetState( STATE_PARSE_BOUNDARY );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing airport boundary: " << line);
|
||||
// ParseBoundry(line);
|
||||
break;
|
||||
|
||||
case NODE_CODE:
|
||||
case BEZIER_NODE_CODE:
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing node: " << line);
|
||||
cur_node = ParseNode( code, line, prev_node );
|
||||
|
||||
if ( prev_node && (cur_node != prev_node) )
|
||||
{
|
||||
// prev node is done - process it\n");
|
||||
if ( cur_state == STATE_PARSE_PAVEMENT )
|
||||
{
|
||||
cur_pavement->AddNode( prev_node );
|
||||
}
|
||||
else if ( cur_state == STATE_PARSE_FEATURE )
|
||||
{
|
||||
cur_feat->AddNode( prev_node );
|
||||
}
|
||||
}
|
||||
|
||||
prev_node = cur_node;
|
||||
break;
|
||||
|
||||
case CLOSE_NODE_CODE:
|
||||
case CLOSE_BEZIER_NODE_CODE:
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing close loop node: " << line);
|
||||
cur_node = ParseNode( code, line, prev_node );
|
||||
|
||||
if ( cur_state == STATE_PARSE_PAVEMENT )
|
||||
{
|
||||
if (cur_node != prev_node)
|
||||
{
|
||||
cur_pavement->AddNode( prev_node );
|
||||
cur_pavement->AddNode( cur_node );
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_pavement->AddNode( cur_node );
|
||||
}
|
||||
cur_pavement->CloseCurContour();
|
||||
}
|
||||
else if ( cur_state == STATE_PARSE_FEATURE )
|
||||
{
|
||||
if (cur_node != prev_node)
|
||||
{
|
||||
cur_feat->AddNode( prev_node );
|
||||
cur_feat->AddNode( cur_node );
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_feat->AddNode( cur_node );
|
||||
}
|
||||
if (cur_airport)
|
||||
{
|
||||
cur_airport->AddFeature( cur_feat );
|
||||
}
|
||||
SetState( STATE_NONE );
|
||||
}
|
||||
prev_node = NULL;
|
||||
cur_node = NULL;
|
||||
break;
|
||||
|
||||
case TERM_NODE_CODE:
|
||||
case TERM_BEZIER_NODE_CODE:
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing termination node: " << line);
|
||||
cur_node = ParseNode( code, line, prev_node );
|
||||
|
||||
if ( cur_state == STATE_PARSE_FEATURE )
|
||||
{
|
||||
if (cur_node != prev_node)
|
||||
{
|
||||
cur_feat->AddNode( prev_node );
|
||||
cur_feat->AddNode( cur_node );
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_feat->AddNode( cur_node );
|
||||
}
|
||||
if (cur_airport)
|
||||
{
|
||||
cur_airport->AddFeature( cur_feat );
|
||||
}
|
||||
SetState( STATE_NONE );
|
||||
}
|
||||
prev_node = NULL;
|
||||
cur_node = NULL;
|
||||
break;
|
||||
|
||||
case AIRPORT_VIEWPOINT_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing viewpoint: " << line);
|
||||
break;
|
||||
case AIRPLANE_STARTUP_LOCATION_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing airplane startup location: " << line);
|
||||
break;
|
||||
case LIGHT_BEACON_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing light beacon: " << line);
|
||||
break;
|
||||
case WINDSOCK_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing windsock: " << line);
|
||||
break;
|
||||
case TAXIWAY_SIGN:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing taxiway sign: " << line);
|
||||
break;
|
||||
case LIGHTING_OBJECT:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing lighting object: " << line);
|
||||
break;
|
||||
case COMM_FREQ1_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 1: " << line);
|
||||
break;
|
||||
case COMM_FREQ2_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 2: " << line);
|
||||
break;
|
||||
case COMM_FREQ3_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 3: " << line);
|
||||
break;
|
||||
case COMM_FREQ4_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 4: " << line);
|
||||
break;
|
||||
case COMM_FREQ5_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 5: " << line);
|
||||
break;
|
||||
case COMM_FREQ6_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 6: " << line);
|
||||
break;
|
||||
case COMM_FREQ7_CODE:
|
||||
SetState( STATE_PARSE_SIMPLE );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 7: " << line);
|
||||
break;
|
||||
case END_OF_FILE :
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Reached end of file");
|
||||
SetState( STATE_DONE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Parser::WriteBtg( const string& root, const string_list& elev_src )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<airports.size(); i++)
|
||||
{
|
||||
airports[i]->BuildBtg( root, elev_src );
|
||||
}
|
||||
}
|
||||
|
||||
osg::Group* Parser::CreateOsgGroup( void )
|
||||
{
|
||||
osg::Group* airportNode = new osg::Group();
|
||||
int i;
|
||||
|
||||
for (i=0; i<airports.size(); i++)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Add airport " << i << " to node");
|
||||
airports[i]->BuildOsg( airportNode );
|
||||
}
|
||||
|
||||
return airportNode;
|
||||
}
|
||||
|
99
src/Airports/GenAirports850/parser.hxx
Normal file
99
src/Airports/GenAirports850/parser.hxx
Normal file
|
@ -0,0 +1,99 @@
|
|||
#ifndef _PARSER_H_
|
||||
#define _PARSER_H_
|
||||
|
||||
#include "beznode.hxx"
|
||||
#include "closedpoly.hxx"
|
||||
#include "linearfeature.hxx"
|
||||
#include "runway.hxx"
|
||||
#include "airport.hxx"
|
||||
|
||||
#define STATE_NONE (0)
|
||||
#define STATE_PARSE_SIMPLE (1)
|
||||
#define STATE_PARSE_BOUNDARY (2)
|
||||
#define STATE_PARSE_PAVEMENT (3)
|
||||
#define STATE_PARSE_FEATURE (4)
|
||||
#define STATE_DONE (10)
|
||||
|
||||
#define MAXLINE (256)
|
||||
|
||||
#define LAND_AIRPORT_CODE (1)
|
||||
#define SEA_AIRPORT_CODE (16)
|
||||
#define HELIPORT_CODE (17)
|
||||
|
||||
#define LAND_RUNWAY_CODE (100)
|
||||
#define WATER_RUNWAY_CODE (101)
|
||||
#define HELIPAD_CODE (102)
|
||||
|
||||
#define PAVEMENT_CODE (110)
|
||||
#define LINEAR_FEATURE_CODE (120)
|
||||
#define BOUNDRY_CODE (130)
|
||||
|
||||
#define NODE_CODE (111)
|
||||
#define BEZIER_NODE_CODE (112)
|
||||
#define CLOSE_NODE_CODE (113)
|
||||
#define CLOSE_BEZIER_NODE_CODE (114)
|
||||
#define TERM_NODE_CODE (115)
|
||||
#define TERM_BEZIER_NODE_CODE (116)
|
||||
|
||||
#define AIRPORT_VIEWPOINT_CODE (14)
|
||||
#define AIRPLANE_STARTUP_LOCATION_CODE (15)
|
||||
#define LIGHT_BEACON_CODE (18)
|
||||
#define WINDSOCK_CODE (19)
|
||||
#define TAXIWAY_SIGN (20)
|
||||
#define LIGHTING_OBJECT (21)
|
||||
|
||||
#define COMM_FREQ1_CODE (50)
|
||||
#define COMM_FREQ2_CODE (51)
|
||||
#define COMM_FREQ3_CODE (52)
|
||||
#define COMM_FREQ4_CODE (53)
|
||||
#define COMM_FREQ5_CODE (54)
|
||||
#define COMM_FREQ6_CODE (55)
|
||||
#define COMM_FREQ7_CODE (56)
|
||||
|
||||
#define END_OF_FILE (99)
|
||||
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
Parser(string& f)
|
||||
{
|
||||
filename = f;
|
||||
cur_airport = NULL;
|
||||
cur_pavement = NULL;
|
||||
cur_feat = NULL;
|
||||
prev_node = NULL;
|
||||
cur_state = STATE_NONE;
|
||||
}
|
||||
|
||||
int Parse( char* icao );
|
||||
void WriteBtg( const string& root, const string_list& elev_src );
|
||||
osg::Group* CreateOsgGroup( void );
|
||||
|
||||
private:
|
||||
int SetState( int state );
|
||||
|
||||
BezNode* ParseNode( int type, char* line, BezNode* prevNode );
|
||||
LinearFeature* ParseFeature( char* line );
|
||||
ClosedPoly* ParsePavement( char* line );
|
||||
osg::Geode* ParseRunway(char* line );
|
||||
int ParseLine( char* line );
|
||||
|
||||
// int ParseBoundry(char* line, Node* airport);
|
||||
|
||||
string filename;
|
||||
|
||||
// a polygon conists of an array of contours
|
||||
// (first is outside boundry, remaining are holes)
|
||||
Airport* cur_airport;
|
||||
Runway* cur_runway;
|
||||
ClosedPoly* cur_pavement;
|
||||
LinearFeature* cur_feat;
|
||||
BezNode* prev_node;
|
||||
|
||||
AirportList airports;
|
||||
|
||||
int cur_state;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,49 +1,113 @@
|
|||
// 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/compiler.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
|
||||
#include "beznode.hxx"
|
||||
#include "runway.hxx"
|
||||
#include "point2d.hxx"
|
||||
|
||||
extern int nudge;
|
||||
|
||||
// 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 )
|
||||
Runway::Runway(char* definition)
|
||||
{
|
||||
double az2;
|
||||
|
||||
// format:
|
||||
// runway width surface shoulder smoothness centerline lights edge lighting distance remaining signs
|
||||
// 100 46.02 2 1 0.00 1 2 1
|
||||
//
|
||||
// runway number runway end lat runway end long threshold overrun markings approach lighting
|
||||
// 09L 33.63470475 -084.44798671 0.00 120.09 3 7
|
||||
//
|
||||
// touchdown zone lighting runway end identifier lights
|
||||
// 0 1
|
||||
//
|
||||
// runway number runway end lat runway end long threshold overrun markings approach lighting
|
||||
// 27R 33.63469907 -084.40893004 0.00 120.09 3 6
|
||||
//
|
||||
// touchdown zone lighting runway end identifier lights
|
||||
// 0 1
|
||||
|
||||
// Parse the line
|
||||
// 46.02 2 1 0.00 1 2 1 09L 33.63470475 -084.44798671 0.00 120.09 3 7 0 1 27R 33.63469907 -084.40893004 0.00 120.09 3 6 0 1
|
||||
|
||||
// int fscanf(FILE *stream, const char *format, ...);
|
||||
sscanf(definition, "%lf %d %d %lf %d %d %d %s %lf %lf %lf %lf %d %d %d %d %s %lf %lf %lf %lf %d %d %d %d",
|
||||
&width, &surface, &shoulder, &smoothness, ¢erline_lights, &edge_lights, &dist_remain_signs,
|
||||
rwnum[0], &lat[0], &lon[0], &threshold[0], &overrun[0], &marking[0], &approach_lights[0], &tz_lights[0], &reil[0],
|
||||
rwnum[1], &lat[1], &lon[1], &threshold[1], &overrun[1], &marking[1], &approach_lights[1], &tz_lights[1], &reil[1]
|
||||
);
|
||||
|
||||
// calculate runway heading and length (used a lot)
|
||||
geo_inverse_wgs_84( lat[0], lon[0], lat[1], lon[1], &heading, &az2, &length );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Read runway: (" << lon[0] << "," << lat[0] << ") to (" << lon[1] << "," << lat[1] << ") heading: " << heading << " length: " << length << " width: " << width );
|
||||
}
|
||||
|
||||
int Runway::BuildOsg ( osg::Group* airport )
|
||||
{
|
||||
// calculated distance, and azimuths
|
||||
double az1, az2, dist;
|
||||
|
||||
// rectangle verticies
|
||||
double v0_lat, v0_lon, v1_lat, v1_lon, v2_lat, v2_lon, v3_lat, v3_lon;
|
||||
|
||||
// Create a node for the runway
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
osg::Vec3dArray& v = *(new osg::Vec3dArray(4));
|
||||
|
||||
// first, find the runway direction vector
|
||||
// static int geo_inverse_wgs_84( double lat1, double lon1, double lat2, double lon2, double *az1, double *az2, double *s )
|
||||
geo_inverse_wgs_84( lat[0], lon[0], lat[1], lon[1], &az1, &az2, &dist);
|
||||
|
||||
// now, need to caculate the 4 verticies
|
||||
// static int geo_direct_wgs_84( double lat1, double lon1, double az1, double s, double *lat2, double *lon2, double *az2 )
|
||||
geo_direct_wgs_84( lat[0], lon[0], az1+90, width/2, &v0_lat, &v0_lon, &az2 );
|
||||
geo_direct_wgs_84( v0_lat, v0_lon, az1, dist, &v1_lat, &v1_lon, &az2 );
|
||||
geo_direct_wgs_84( v1_lat, v1_lon, az1-90, width, &v2_lat, &v2_lon, &az2 );
|
||||
geo_direct_wgs_84( v2_lat, v2_lon, az1+180, dist, &v3_lat, &v3_lon, &az2 );
|
||||
|
||||
// convert from lat/lon to geodisc
|
||||
// (maybe later) - check some simgear objects...
|
||||
v[0].set(v0_lat, v0_lon, 0.0f);
|
||||
v[1].set(v1_lat, v1_lon, 0.0f);
|
||||
v[2].set(v2_lat, v2_lon, 0.0f);
|
||||
v[3].set(v3_lat, v3_lon, 0.0f);
|
||||
|
||||
geometry->setVertexArray(&v);
|
||||
|
||||
osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_TRIANGLE_STRIP,4));
|
||||
geometry->addPrimitiveSet(&drawElements);
|
||||
|
||||
drawElements[0] = 3;
|
||||
drawElements[1] = 0;
|
||||
drawElements[2] = 2;
|
||||
drawElements[3] = 1;
|
||||
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
airport->addChild( geode );
|
||||
|
||||
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;
|
||||
|
@ -111,53 +175,19 @@ TGPolygon gen_wgs84_area( Point3D origin,
|
|||
}
|
||||
|
||||
|
||||
// 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,
|
||||
0.0, 0.0,
|
||||
runway.width*width_scale,
|
||||
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 Runway::gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend )
|
||||
{
|
||||
TGPolygon result_list;
|
||||
Point3D origin(runway.lon, runway.lat, 0);
|
||||
Point3D origin = GetMidpoint();
|
||||
|
||||
result_list
|
||||
= gen_wgs84_area( origin,
|
||||
runway.length + 2.0*length_extend,
|
||||
displ1, displ2,
|
||||
runway.width + 2.0*width_extend,
|
||||
runway.heading, alt_m, false );
|
||||
result_list = gen_wgs84_area( origin, length + 2.0*length_extend, displ1, displ2, width + 2.0*width_extend, 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 ) {
|
||||
for ( int i = 0; i < result_list.contour_size( 0 ); ++i )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " " << result_list.get_pt(0, i));
|
||||
}
|
||||
|
||||
|
@ -166,26 +196,253 @@ TGPolygon gen_runway_area_w_extend( const TGRunway& runway,
|
|||
|
||||
|
||||
// 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 Runway::gen_runway_w_mid( double alt_m, double length_extend_m, double width_extend_m )
|
||||
{
|
||||
TGPolygon result_list;
|
||||
Point3D origin(runway.lon, runway.lat, 0);
|
||||
Point3D origin = GetMidpoint();
|
||||
|
||||
result_list = gen_wgs84_area( origin,
|
||||
runway.length
|
||||
+ 2.0*length_extend_m,
|
||||
0.0, 0.0,
|
||||
runway.width
|
||||
+ 2.0 * width_extend_m,
|
||||
runway.heading, alt_m, true );
|
||||
result_list = gen_wgs84_area( origin, length + 2.0*length_extend_m, 0.0, 0.0, width + 2.0 * width_extend_m, 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 ) {
|
||||
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;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Runway::gen_simple_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum )
|
||||
{
|
||||
Point3D mp, end[2];
|
||||
int i;
|
||||
|
||||
// create the runway in two halves, as markings may be different in each direction
|
||||
end[0] = GetStart();
|
||||
mp = GetMidpoint();
|
||||
end[1] = GetEnd();
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
gen_simple_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Runway::gen_simple_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum )
|
||||
{
|
||||
int j, k;
|
||||
|
||||
TGPolygon runway = gen_runway_w_mid( 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), width, length/2.0, 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), width, length/2.0, heading+180.0 );
|
||||
texparams->push_back( tp );
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
gen_runway_stopway( rwy_info, runway_a, runway_b,
|
||||
material,
|
||||
rwy_polys, texparams, accum );
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Runway::gen_marked_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum )
|
||||
{
|
||||
Point3D mp, end[2];
|
||||
int i;
|
||||
|
||||
// create the runway in two halves, as markings may be different in each direction
|
||||
end[0] = GetStart();
|
||||
mp = GetMidpoint();
|
||||
end[1] = GetEnd();
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
// first, create half 'a'
|
||||
switch( marking[i] )
|
||||
{
|
||||
case 0:
|
||||
case 1: // Visual
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has Visual marking");
|
||||
gen_visual_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
|
||||
break;
|
||||
|
||||
case 2: // non-precision
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has Non Precision marking");
|
||||
gen_non_precision_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
|
||||
break;
|
||||
|
||||
case 3: // precision
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has Precision marking");
|
||||
//gen_precision_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
|
||||
gen_simple_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
|
||||
break;
|
||||
|
||||
default: // unknown
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has unknown marking");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
|
||||
{
|
||||
TGPolygon base, safe_base;
|
||||
string material;
|
||||
|
||||
if ( surface == 1 /* Asphalt */ )
|
||||
{
|
||||
material = "pa_tiedown";
|
||||
}
|
||||
else if ( surface == 2 /* Concrete */ )
|
||||
{
|
||||
material = "pc_tiedown";
|
||||
}
|
||||
else if ( surface == 3 /* Turf/Grass */ )
|
||||
{
|
||||
material = "grass_rwy";
|
||||
}
|
||||
else if ( surface == 4 /* Dirt */ || surface == 5 /* Gravel */ )
|
||||
{
|
||||
material = "dirt_rwy";
|
||||
}
|
||||
else if ( surface == 12 /* Dry Lakebed */ )
|
||||
{
|
||||
material = "dirt_rwy";
|
||||
}
|
||||
else if ( surface == 13 /* Water runway (buoy's?) */ )
|
||||
{
|
||||
// water
|
||||
}
|
||||
else
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "surface_code = " << surface);
|
||||
throw sg_exception("unknown runway type!");
|
||||
}
|
||||
|
||||
// first, check the surface type - anything but concrete and asphalt are easy
|
||||
switch( surface )
|
||||
{
|
||||
case 1: // asphalt:
|
||||
case 2: // concrete
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: asphalt or concrete" << surface);
|
||||
gen_simple_rwy( alt_m, material, rwy_polys, texparams, accum );
|
||||
break;
|
||||
|
||||
case 3: // Grass
|
||||
case 4: // Dirt
|
||||
case 5: // Gravel
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: Turf, Dirt or Gravel" << surface );
|
||||
gen_simple_rwy( alt_m, material, rwy_polys, texparams, accum );
|
||||
break;
|
||||
|
||||
case 12: // dry lakebed
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: Dry Lakebed");
|
||||
break;
|
||||
|
||||
case 13: // water
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: Water");
|
||||
break;
|
||||
|
||||
case 14: // snow
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: Snow");
|
||||
break;
|
||||
|
||||
case 15: // transparent
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: transparent");
|
||||
break;
|
||||
|
||||
default: // unknown
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: unknown" << surface);
|
||||
break;
|
||||
}
|
||||
|
||||
// generate area around runways
|
||||
base = gen_runway_area_w_extend( 0.0, 20.0, -overrun[0], -overrun[1], 20.0 );
|
||||
|
||||
// also clear a safe area around the runway
|
||||
safe_base = gen_runway_area_w_extend( 0.0, 180.0, -overrun[0], -overrun[1], 50.0 );
|
||||
|
||||
// add this to the airport clearing
|
||||
*apt_clearing = tgPolygonUnion(safe_base, *apt_clearing);
|
||||
|
||||
// and add the clearing to the base
|
||||
*apt_base = tgPolygonUnion( base, *apt_base );
|
||||
}
|
||||
|
|
|
@ -1,129 +1,84 @@
|
|||
// 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_H_
|
||||
#define _RUNWAY_H_
|
||||
|
||||
|
||||
#ifndef _RUNWAY_HXX
|
||||
#define _RUNWAY_HXX
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Geometry/point3d.hxx>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
#include <Geometry/point3d.hxx>
|
||||
|
||||
#include "texparams.hxx"
|
||||
|
||||
struct TGRunway {
|
||||
int type;
|
||||
std::string rwy_no1;
|
||||
std::string rwy_no2;
|
||||
#include <osg/Group>
|
||||
|
||||
double lon;
|
||||
double lat;
|
||||
double heading;
|
||||
double length;
|
||||
double width;
|
||||
double disp_thresh1;
|
||||
double disp_thresh2;
|
||||
double stopway1;
|
||||
double stopway2;
|
||||
using std::string;
|
||||
|
||||
int surface_code;
|
||||
int shoulder_code;
|
||||
double smoothness;
|
||||
bool centre_lights;
|
||||
int edge_lights;
|
||||
int marking_code1;
|
||||
int marking_code2;
|
||||
int alc1_flag;
|
||||
int alc2_flag;
|
||||
bool has_tdz1;
|
||||
bool has_tdz2;
|
||||
int reil1;
|
||||
int reil2;
|
||||
class Runway
|
||||
{
|
||||
public:
|
||||
Runway(char* def);
|
||||
|
||||
bool dist_remaining;
|
||||
bool IsPrecision()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
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 generated;
|
||||
Point3D GetStart(void)
|
||||
{
|
||||
return ( Point3D( lon[0], lat[0], 0.0f ));
|
||||
}
|
||||
|
||||
Point3D GetEnd(void)
|
||||
{
|
||||
return ( Point3D( lon[1], lat[1], 0.0f ));
|
||||
}
|
||||
|
||||
Point3D GetMidpoint(void)
|
||||
{
|
||||
return ( Point3D( (lon[0]+lon[1])/2.0f, (lat[0]+lat[1])/2.0f, 0.0f) );
|
||||
}
|
||||
|
||||
int BuildOsg( osg::Group* airport );
|
||||
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
|
||||
|
||||
private:
|
||||
// data for whole runway
|
||||
int surface;
|
||||
int shoulder;
|
||||
int centerline_lights;
|
||||
int edge_lights;
|
||||
int dist_remain_signs;
|
||||
|
||||
double width;
|
||||
double length;
|
||||
double heading;
|
||||
double smoothness;
|
||||
|
||||
// data for each end
|
||||
char rwnum[2][16];
|
||||
double lat[2];
|
||||
double lon[2];
|
||||
double threshold[2];
|
||||
double overrun[2];
|
||||
|
||||
int marking[2];
|
||||
int approach_lights[2];
|
||||
int tz_lights[2];
|
||||
int reil[2];
|
||||
|
||||
// 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 );
|
||||
// void gen_runway_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,
|
||||
// const string& prefix, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum );
|
||||
// void gen_runway_stopway( const TGPolygon& runway_a, const TGPolygon& runway_b, const string& prefix, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon* accum );
|
||||
TGPolygon gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend );
|
||||
|
||||
void gen_simple_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum );
|
||||
void gen_marked_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum );
|
||||
};
|
||||
typedef std::vector < TGRunway > runway_list;
|
||||
typedef runway_list::iterator runway_list_iterator;
|
||||
typedef runway_list::const_iterator const_runway_list_iterator;
|
||||
|
||||
struct TGLightobj {
|
||||
double lon;
|
||||
double lat;
|
||||
int type;
|
||||
double heading;
|
||||
double glideslope;
|
||||
std::string rwy_name;
|
||||
};
|
||||
typedef std::vector < TGLightobj > light_list;
|
||||
typedef light_list::iterator light_list_iterator;
|
||||
typedef light_list::const_iterator const_light_list_iterator;
|
||||
typedef std::vector <Runway *> RunwayList;
|
||||
|
||||
|
||||
|
||||
|
||||
// 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
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue