1
0
Fork 0

[helipad] Maintenance

This commit is contained in:
scttgs0 2023-05-14 11:16:44 -05:00
parent 95c62c0f30
commit 9a2a4cdb25
2 changed files with 96 additions and 106 deletions

View file

@ -17,11 +17,11 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include "global.hxx"
#include "apt_math.hxx" #include "apt_math.hxx"
#include "debug.hxx"
#include "global.hxx"
#include "helipad.hxx" #include "helipad.hxx"
#include "runway.hxx" #include "runway.hxx"
#include "debug.hxx"
Helipad::Helipad(char* definition) Helipad::Helipad(char* definition)
@ -32,22 +32,13 @@ Helipad::Helipad(char* definition)
// "H1 21.30433555 -157.85586778 0.00 10.70 10.70 2 0 0 0.25 0\r" // "H1 21.30433555 -157.85586778 0.00 10.70 10.70 2 0 0 0.25 0\r"
std::istringstream ss(definition); std::istringstream ss(definition);
ss >> heli.designator ss >> heli.designator >> heli.lat >> heli.lon >> heli.heading >> heli.length >> heli.width >> heli.surface >> heli.marking >> heli.shoulder >> heli.smoothness >> heli.edge_lights;
>> heli.lat
>> heli.lon
>> heli.heading
>> heli.length
>> heli.width
>> heli.surface
>> heli.marking
>> heli.shoulder
>> heli.smoothness
>> heli.edge_lights;
TG_LOG(SG_GENERAL, SG_DEBUG, "Read helipad: (" << heli.lon << "," << heli.lat << ") heading: " << heli.heading << " length: " << heli.length << " width: " << heli.width ); TG_LOG(SG_GENERAL, SG_DEBUG, "Read helipad: (" << heli.lon << "," << heli.lat << ") heading: " << heli.heading << " length: " << heli.length << " width: " << heli.width);
} }
tglightcontour_list Helipad::gen_helipad_lights(double maxsize) { tglightcontour_list Helipad::gen_helipad_lights(double maxsize)
{
tglightcontour_list result; tglightcontour_list result;
// Vector calculation // Vector calculation
@ -57,30 +48,30 @@ tglightcontour_list Helipad::gen_helipad_lights(double maxsize) {
tgContour area = gen_helipad_area_w_extend(0.0, 0.0); tgContour area = gen_helipad_area_w_extend(0.0, 0.0);
tgLightContour yellow; tgLightContour yellow;
yellow.SetType( "RWY_YELLOW_LIGHTS" ); yellow.SetType("RWY_YELLOW_LIGHTS");
for ( unsigned int i = 0; i < area.GetSize(); ++i ) { for (unsigned int i = 0; i < area.GetSize(); ++i) {
double dist, course, cs; double dist, course, cs;
SGGeodesy::inverse(area.GetNode(i), area.GetNode(i==3 ? 0 : i+1), course, cs, dist ); SGGeodesy::inverse(area.GetNode(i), area.GetNode(i == 3 ? 0 : i + 1), course, cs, dist);
int divs = (int)(dist / 5.0); int divs = (int)(dist / 5.0);
double step = dist/divs; double step = dist / divs;
SGGeod pt = area.GetNode(i); SGGeod pt = area.GetNode(i);
for (int j = 0; j < divs; ++j) { for (int j = 0; j < divs; ++j) {
pt = SGGeodesy::direct(pt, course, step ); pt = SGGeodesy::direct(pt, course, step);
yellow.AddLight( pt, vec ); yellow.AddLight(pt, vec);
} }
} }
// Create a circle of yellow lights where the white texture circle is // Create a circle of yellow lights where the white texture circle is
for (int deg = 0; deg < 360; deg += 45){ for (int deg = 0; deg < 360; deg += 45) {
yellow.AddLight( SGGeodesy::direct(GetLoc(), deg, maxsize * 0.46), vec ); yellow.AddLight(SGGeodesy::direct(GetLoc(), deg, maxsize * 0.46), vec);
} }
result.push_back( yellow ); result.push_back(yellow);
return result; return result;
} }
void Helipad::build_helipad_shoulders( const tgContour& outer_area ) void Helipad::build_helipad_shoulders(const tgContour& outer_area)
{ {
double shoulder_width, shoulder_heading; double shoulder_width, shoulder_heading;
std::string shoulder_mat; std::string shoulder_mat;
@ -93,10 +84,10 @@ void Helipad::build_helipad_shoulders( const tgContour& outer_area )
shoulder_mat = "pc_shoulder"; shoulder_mat = "pc_shoulder";
shoulder_width = 6; // shoulder size in m shoulder_width = 6; // shoulder size in m
} else if (heli.surface == 1) { } else if (heli.surface == 1) {
shoulder_mat = "pa_shoulder_f"; shoulder_mat = "pa_shoulder_f";
shoulder_width = 1; // shoulder size in m shoulder_width = 1; // shoulder size in m
} else { } else {
shoulder_mat = "pc_shoulder_f"; shoulder_mat = "pc_shoulder_f";
shoulder_width = 1; // shoulder size in m shoulder_width = 1; // shoulder size in m
} }
shoulder_heading = heli.heading; shoulder_heading = heli.heading;
@ -105,25 +96,25 @@ void Helipad::build_helipad_shoulders( const tgContour& outer_area )
tgPolygon shoulder_poly; tgPolygon shoulder_poly;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
shoulder_heading = SGMiscd::normalizePeriodic(0,360,shoulder_heading-90); shoulder_heading = SGMiscd::normalizePeriodic(0, 360, shoulder_heading - 90);
shoulder_poly.Erase(); shoulder_poly.Erase();
shoulder_poly.AddNode( 0, shoulder.GetNode( i ) ); shoulder_poly.AddNode(0, shoulder.GetNode(i));
shoulder_poly.AddNode( 0, shoulder.GetNode( i == 3 ? 0 : i+1 ) ); shoulder_poly.AddNode(0, shoulder.GetNode(i == 3 ? 0 : i + 1));
shoulder_poly.AddNode( 0, outer_area.GetNode( i == 3 ? 0 : i+1 ) ); shoulder_poly.AddNode(0, outer_area.GetNode(i == 3 ? 0 : i + 1));
shoulder_poly.AddNode( 0, outer_area.GetNode( i ) ); shoulder_poly.AddNode(0, outer_area.GetNode(i));
shoulder_poly.SetMaterial( shoulder_mat ); shoulder_poly.SetMaterial(shoulder_mat);
shoulder_poly.SetTexParams( shoulder_poly.GetNode(0, 1), shoulder_width, 5.0, shoulder_heading ); shoulder_poly.SetTexParams(shoulder_poly.GetNode(0, 1), shoulder_width, 5.0, shoulder_heading);
shoulder_poly.SetTexLimits( 1,1,0,0 ); shoulder_poly.SetTexLimits(1, 1, 0, 0);
shoulder_poly.SetTexMethod( TG_TEX_BY_TPS_CLIPU, 0.0, 0.0, 1.0, 1.0 ); shoulder_poly.SetTexMethod(TG_TEX_BY_TPS_CLIPU, 0.0, 0.0, 1.0, 1.0);
shoulder_poly = tgPolygon::Snap( shoulder_poly, gSnap ); shoulder_poly = tgPolygon::Snap(shoulder_poly, gSnap);
shoulder_polys.push_back( shoulder_poly ); shoulder_polys.push_back(shoulder_poly);
} }
} }
void Helipad::BuildBtg( tgpolygon_list& rwy_polys, void Helipad::BuildBtg(tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights, tglightcontour_list& rwy_lights,
tgcontour_list& slivers, tgcontour_list& slivers,
tgAccumulator& accum ) tgAccumulator& accum)
{ {
// //
// Generate the basic helipad outlines // Generate the basic helipad outlines
@ -131,97 +122,96 @@ void Helipad::BuildBtg( tgpolygon_list& rwy_polys,
double heli_size; double heli_size;
// helipad constructed as a square with width or length added around it // helipad constructed as a square with width or length added around it
if ( heli.width == heli.length ) { if (heli.width == heli.length) {
heli_size = heli.length; heli_size = heli.length;
} else if ( heli.width > heli.length ) { } else if (heli.width > heli.length) {
heli_size = heli.length; heli_size = heli.length;
} else { } else {
heli_size = heli.width; heli_size = heli.width;
} }
tgContour helipad = gen_wgs84_area( GetLoc(), heli_size, 0, 0, heli_size, heli.heading, false); tgContour helipad = gen_wgs84_area(GetLoc(), heli_size, 0, 0, heli_size, heli.heading, false);
helipad = tgContour::Snap( helipad, gSnap ); helipad = tgContour::Snap(helipad, gSnap);
std::string heli_mat, extra_mat; std::string heli_mat, extra_mat;
if (heli.surface == 1) { if (heli.surface == 1) {
heli_mat = "pa_heli"; heli_mat = "pa_heli";
extra_mat = "pa_tiedown"; extra_mat = "pa_tiedown";
} else { } else {
heli_mat = "pc_heli"; heli_mat = "pc_heli";
extra_mat = "pc_tiedown"; extra_mat = "pc_tiedown";
} }
// Clip the new polygon against what ever has already been created. // Clip the new polygon against what ever has already been created.
tgPolygon clipped = accum.Diff( helipad ); tgPolygon clipped = accum.Diff(helipad);
// tgPolygon::RemoveSlivers( clipped, slivers ); // tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with // Split long edges to create an object that can better flow with
// the surface terrain // the surface terrain
tgPolygon heli_poly = tgPolygon::SplitLongEdges( clipped, 400.0 ); tgPolygon heli_poly = tgPolygon::SplitLongEdges(clipped, 400.0);
accum.Add( helipad ); accum.Add(helipad);
heli_poly.SetMaterial( heli_mat ); heli_poly.SetMaterial(heli_mat);
heli_poly.SetTexParams( helipad.GetNode(0), heli_size, heli_size, heli.heading ); heli_poly.SetTexParams(helipad.GetNode(0), heli_size, heli_size, heli.heading);
heli_poly.SetTexLimits( 0,0,1,1 ); heli_poly.SetTexLimits(0, 0, 1, 1);
heli_poly.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, -1.0, -1.0, 1.0, 1.0 ); heli_poly.SetTexMethod(TG_TEX_BY_TPS_CLIPUV, -1.0, -1.0, 1.0, 1.0);
rwy_polys.push_back( heli_poly ); rwy_polys.push_back(heli_poly);
// Now generate the actual rectangle, and clip it with the square // Now generate the actual rectangle, and clip it with the square
// need areference point at the origin of the direction, in the middle of width // need a reference point at the origin of the direction, in the middle of width
SGGeod ref = SGGeodesy::direct( SGGeod::fromDeg(heli.lon, heli.lat), SGGeod ref = SGGeodesy::direct(SGGeod::fromDeg(heli.lon, heli.lat),
SGMiscd::normalizePeriodic(0, 360, heli.heading + 180 ), SGMiscd::normalizePeriodic(0, 360, heli.heading + 180),
heli.length/2 ); heli.length / 2);
tgContour outer_area = gen_wgs84_rect( ref, heli.heading, heli.length, heli.width ); tgContour outer_area = gen_wgs84_rect(ref, heli.heading, heli.length, heli.width);
outer_area = tgContour::Snap( outer_area, gSnap ); outer_area = tgContour::Snap(outer_area, gSnap);
tgPolygon outer_poly = tgContour::Diff( outer_area, heli_poly ); tgPolygon outer_poly = tgContour::Diff(outer_area, heli_poly);
clipped = accum.Diff( outer_poly ); clipped = accum.Diff(outer_poly);
// tgPolygon::RemoveSlivers( clipped, slivers ); // tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with // Split long edges to create an object that can better flow with
// the surface terrain // the surface terrain
tgPolygon extra_heli = tgPolygon::SplitLongEdges( clipped, 400.0 ); tgPolygon extra_heli = tgPolygon::SplitLongEdges(clipped, 400.0);
// Create the final output and push on to the runway super_polygon // Create the final output and push on to the runway super_polygon
// list // list
extra_heli.SetMaterial( extra_mat ); extra_heli.SetMaterial(extra_mat);
extra_heli.SetTexParams( outer_area.GetNode(0), 5.0, 5.0, heli.heading ); extra_heli.SetTexParams(outer_area.GetNode(0), 5.0, 5.0, heli.heading);
extra_heli.SetTexLimits( 1,1,0,0 ); extra_heli.SetTexLimits(1, 1, 0, 0);
extra_heli.SetTexMethod( TG_TEX_BY_TPS_NOCLIP ); extra_heli.SetTexMethod(TG_TEX_BY_TPS_NOCLIP);
rwy_polys.push_back( extra_heli ); rwy_polys.push_back(extra_heli);
accum.Add( extra_heli ); accum.Add(extra_heli);
build_helipad_shoulders( outer_area ); build_helipad_shoulders(outer_area);
if (heli.edge_lights) if (heli.edge_lights) {
{
// Now generate the helipad lights // Now generate the helipad lights
tglightcontour_list s = gen_helipad_lights(heli_size); tglightcontour_list s = gen_helipad_lights(heli_size);
for ( unsigned int i = 0; i < s.size(); ++i ) { for (unsigned int i = 0; i < s.size(); ++i) {
rwy_lights.push_back( s[i] ); rwy_lights.push_back(s[i]);
} }
} }
} }
void Helipad::BuildBtg( tgpolygon_list& rwy_polys, void Helipad::BuildBtg(tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights, tglightcontour_list& rwy_lights,
tgcontour_list& slivers, tgcontour_list& slivers,
tgpolygon_list& apt_base_polys, tgpolygon_list& apt_base_polys,
tgpolygon_list& apt_clearing_polys, tgpolygon_list& apt_clearing_polys,
tgAccumulator& accum ) tgAccumulator& accum)
{ {
BuildBtg( rwy_polys, rwy_lights, slivers, accum ); BuildBtg(rwy_polys, rwy_lights, slivers, accum);
// generate area around helipad // generate area around helipad
double length, width; double length, width;
tgContour base_contour, safe_base_contour; tgContour base_contour, safe_base_contour;
tgPolygon base, safe_base; tgPolygon base, safe_base;
length = heli.length; length = heli.length;
width = heli.width; width = heli.width;
if ( (heli.shoulder == 1) || (heli.shoulder == 2 ) ) { if ((heli.shoulder == 1) || (heli.shoulder == 2)) {
length += 12.0; length += 12.0;
width += 12.0; width += 12.0;
} else { } else {
@ -229,42 +219,42 @@ void Helipad::BuildBtg( tgpolygon_list& rwy_polys,
width += 2.0; width += 2.0;
} }
base_contour = gen_helipad_area_w_extend(length * 0.25 , width * 0.25 ); base_contour = gen_helipad_area_w_extend(length * 0.25, width * 0.25);
base_contour = tgContour::Snap( base_contour, gSnap ); base_contour = tgContour::Snap(base_contour, gSnap);
base.AddContour( base_contour ); base.AddContour(base_contour);
// also clear a safe area around the pad // also clear a safe area around the pad
safe_base_contour = gen_helipad_area_w_extend( length * 0.5, width * 0.5 ); safe_base_contour = gen_helipad_area_w_extend(length * 0.5, width * 0.5);
safe_base_contour = tgContour::Snap( safe_base_contour, gSnap ); safe_base_contour = tgContour::Snap(safe_base_contour, gSnap);
safe_base.AddContour( safe_base_contour ); safe_base.AddContour(safe_base_contour);
// add this to the airport clearing // add this to the airport clearing
apt_clearing_polys.push_back( safe_base ); apt_clearing_polys.push_back(safe_base);
// and add the clearing to the base // and add the clearing to the base
apt_base_polys.push_back( base ); apt_base_polys.push_back(base);
} }
void Helipad::BuildShoulder( tgpolygon_list& rwy_polys, void Helipad::BuildShoulder(tgpolygon_list& rwy_polys,
tgcontour_list& slivers, tgcontour_list& slivers,
tgAccumulator& accum ) tgAccumulator& accum)
{ {
tgPolygon shoulder; tgPolygon shoulder;
for (unsigned int i=0; i<shoulder_polys.size(); i++) { for (unsigned int i = 0; i < shoulder_polys.size(); i++) {
shoulder = shoulder_polys[i]; shoulder = shoulder_polys[i];
// Clip the new polygon against what ever has already been created. // Clip the new polygon against what ever has already been created.
tgPolygon clipped = accum.Diff( shoulder ); tgPolygon clipped = accum.Diff(shoulder);
// tgPolygon::RemoveSlivers( clipped, slivers ); // tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with // Split long edges to create an object that can better flow with
// the surface terrain // the surface terrain
tgPolygon split = tgPolygon::SplitLongEdges( clipped, 400.0 ); tgPolygon split = tgPolygon::SplitLongEdges(clipped, 400.0);
shoulder_polys[i] = split; shoulder_polys[i] = split;
rwy_polys.push_back( shoulder_polys[i] ); rwy_polys.push_back(shoulder_polys[i]);
accum.Add( shoulder ); accum.Add(shoulder);
} }
} }

View file

@ -40,12 +40,12 @@ public:
tgpolygon_list& apt_clearing_polys, tgpolygon_list& apt_clearing_polys,
tgAccumulator& accum); tgAccumulator& accum);
SGGeod GetLoc() SGGeod GetLoc() const
{ {
return SGGeod::fromDeg(heli.lon, heli.lat); return SGGeod::fromDeg(heli.lon, heli.lat);
} }
bool GetsShoulder() bool GetsShoulder() const
{ {
return (heli.surface < 3) ? true : false; return (heli.surface < 3) ? true : false;
} }
@ -57,7 +57,7 @@ public:
private: private:
struct TGRunway { struct TGRunway {
// data for helipad // data for helipad
char designator[16]; std::string designator;
double lat; double lat;
double lon; double lon;
double heading; double heading;
@ -74,7 +74,7 @@ private:
// generate an area for a runway with expansion specified in meters // generate an area for a runway with expansion specified in meters
// (return result points in degrees) // (return result points in degrees)
tgContour gen_helipad_area_w_extend(double length_extend, double width_extend) tgContour gen_helipad_area_w_extend(double length_extend, double width_extend) const
{ {
return (gen_wgs84_area(GetLoc(), heli.length + 2.0 * length_extend, 0.0, 0.0, heli.width + 2.0 * width_extend, heli.heading, false)); return (gen_wgs84_area(GetLoc(), heli.length + 2.0 * length_extend, 0.0, 0.0, heli.width + 2.0 * width_extend, heli.heading, false));
} }