1
0
Fork 0

Add an optimization to BuildBtg - the accumulator is kept in the native

clipping library format, so it doesn't have to be converted / reconverted
between clipping and TGPolygon types for each operation - shaves about
12 seconds from KATL build.
This commit is contained in:
PSadrozinski 2011-10-14 22:12:49 -04:00 committed by Christian Schmitt
parent 59b534616f
commit db1a734b19
16 changed files with 253 additions and 98 deletions

View file

@ -330,14 +330,11 @@ static TGPolygon calc_elevations( TGAptSurface &surf,
void Airport::BuildBtg(const string& root, const string_list& elev_src )
{
ClipPolyType accum;
ClipPolyType line_accum;
TGPolygon apt_base;
TGPolygon apt_clearing;
TGPolygon accum;
accum.erase();
TGPolygon line_accum;
line_accum.erase();
// runways
superpoly_list rwy_polys;
texparams_list rwy_tps;
@ -486,7 +483,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
boundary->BuildBtg( altitude, &apt_base, &apt_clearing );
}
if ( apt_base.total_size() == 0 )
if ( apt_base.total_size() == 0 )
{
SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated");
return;

View file

@ -112,7 +112,7 @@ void gen_tex_section( const TGPolygon& runway,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum ) {
ClipPolyType *accum ) {
int j, k;

View file

@ -24,6 +24,6 @@ void gen_tex_section( const TGPolygon& runway,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum );
ClipPolyType *accum );
#endif

View file

@ -589,7 +589,7 @@ int ClosedPoly::BuildOsg( osg::Group* airport )
}
}
int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, ClipPolyType* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
{
TGPolygon base, safe_base;
string material;

View file

@ -32,7 +32,7 @@ public:
int BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clearing );
// Build BTG for pavements for airports with no boundary
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, ClipPolyType* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
FeatureList* GetFeatures()
{

View file

@ -79,7 +79,7 @@ void Helipad::BuildBtg( float alt_m,
superpoly_list *rwy_polys,
texparams_list *texparams,
superpoly_list *rwy_lights,
TGPolygon *accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
ClipPolyType *accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
{
SG_LOG( SG_GENERAL, SG_INFO, "Building helipad = " << heli.designator );

View file

@ -28,7 +28,7 @@ class Helipad
{
public:
Helipad(char* def);
void BuildBtg( float alt_m, superpoly_list* heli_polys, texparams_list* texparams, superpoly_list* heli_lights, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
void BuildBtg( float alt_m, superpoly_list* heli_polys, texparams_list* texparams, superpoly_list* heli_lights, ClipPolyType* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
private:
struct TGRunway {

View file

@ -772,7 +772,7 @@ int LinearFeature::Finish()
}
}
int LinearFeature::BuildBtg(float alt_m, superpoly_list* line_polys, texparams_list* line_tps, TGPolygon* line_accum, superpoly_list* lights )
int LinearFeature::BuildBtg(float alt_m, superpoly_list* line_polys, texparams_list* line_tps, ClipPolyType* line_accum, superpoly_list* lights )
{
TGPolygon poly;
TGPolygon clipped;

View file

@ -93,7 +93,7 @@ public:
int Finish();
int BuildOsg( osg::Group* airport );
int BuildBtg( float alt_m, superpoly_list* line_polys, texparams_list* line_tps, TGPolygon* line_accum, superpoly_list* lights );
int BuildBtg( float alt_m, superpoly_list* line_polys, texparams_list* line_tps, ClipPolyType* line_accum, superpoly_list* lights );
private:
Point3D OffsetPointFirst( Point3D *cur, Point3D *next, double offset_by );

View file

@ -128,7 +128,7 @@ TGPolygon WaterRunway::GetNodes()
}
int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, ClipPolyType* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
{
TGPolygon base, safe_base;
string material;

View file

@ -42,7 +42,7 @@ public:
}
int BuildOsg( osg::Group* airport );
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, ClipPolyType* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
private:
struct TGRunway {
@ -93,7 +93,7 @@ private:
double &start_pct, double &end_pct,
superpoly_list* rwy_polys,
texparams_list* texparams,
TGPolygon* accum );
ClipPolyType* accum );
// generate the runway overrun area
void gen_runway_overrun( const TGPolygon& runway_half,
@ -101,7 +101,7 @@ private:
const std::string& prefix,
superpoly_list* rwy_polys,
texparams_list* texparams,
TGPolygon* accum );
ClipPolyType* accum );
// generate a section of runway
void gen_runway_section( const TGPolygon& runway,
@ -113,14 +113,14 @@ private:
const std::string& material,
superpoly_list* rwy_polys,
texparams_list* texparams,
TGPolygon* accum );
ClipPolyType* accum );
void gen_simple_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum );
void gen_simple_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, ClipPolyType *accum );
void gen_rwy( double alt_m,
const std::string& material,
superpoly_list* rwy_polys,
texparams_list* texparams,
TGPolygon* accum );
ClipPolyType* accum );
void gen_rw_marking( const TGPolygon& runway,
double &start1_pct, double &end1_pct,
@ -128,7 +128,7 @@ private:
const string& material,
superpoly_list* rwy_polys,
texparams_list* texparams,
TGPolygon* accum, int marking);
ClipPolyType* accum, int marking);
void gen_runway_lights( float alt_m, superpoly_list* lights );

View file

@ -40,7 +40,7 @@ void Runway::gen_rw_designation( const string& material,
double &start_pct, double &end_pct,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum )
ClipPolyType *accum )
{
if (rwname != "XX"){ /* Do not create a designation block if the runway name is set to none */
string letter = "";
@ -118,7 +118,7 @@ void Runway::gen_runway_overrun( const TGPolygon& runway_half,
const string& prefix,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon* accum ) {
ClipPolyType* accum ) {
const float length = rwy.length / 2.0 + 2.0 * SG_FEET_TO_METER;
double start1_pct = 0.0;
double end1_pct = 0.0;
@ -171,7 +171,7 @@ void Runway::gen_runway_section( const TGPolygon& runway,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum ) {
ClipPolyType *accum ) {
gen_tex_section( runway,
startl_pct, endl_pct,
startw_pct, endw_pct,

View file

@ -40,7 +40,7 @@ void Runway::gen_rw_marking( const TGPolygon& runway,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum, int marking) {
ClipPolyType *accum, int marking) {
std::vector<sections> rw_marking_list;
@ -139,7 +139,7 @@ void Runway::gen_rwy( double alt_m,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum )
ClipPolyType *accum )
{
SG_LOG( SG_GENERAL, SG_INFO, "Building runway = " << rwy.rwnum[0] << " / " << rwy.rwnum[1]);

View file

@ -37,7 +37,7 @@ void Runway::gen_simple_rwy( double alt_m,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
TGPolygon *accum )
ClipPolyType *accum )
{
int i;

View file

@ -26,15 +26,6 @@
// http://www.cs.man.ac.uk/aig/staff/alan/software/
//
// which clipping lib to use?
//#define CLIP_GPC
#define CLIP_CLIPPER
#ifdef CLIP_GPC
extern "C" {
#include <gpc.h>
}
#endif
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
@ -48,11 +39,6 @@ extern "C" {
#include "polygon.hxx"
#include "point2d.hxx"
#ifdef CLIP_CLIPPER
#include "clipper.hpp"
using namespace ClipperLib;
#endif
using std::endl;
// Constructor
@ -361,6 +347,18 @@ void make_gpc_poly( const TGPolygon& in, gpc_polygon *out ) {
delete [] v_list.vertex;
}
void make_tg_poly( const gpc_polygon* in, TGPolygon *out )
{
for ( int i = 0; i < in->num_contours; ++i ) {
for ( int j = 0; j < in->contour[i].num_vertices; j++ ) {
Point3D p( in->contour[i].vertex[j].x, in->contour[i].vertex[j].y, -9999.0 );
out->add_node(i, p);
}
out->set_hole_flag( i, in->hole[i] );
}
}
// Generic clipping routine
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
const TGPolygon& clip )
@ -399,14 +397,7 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
gpc_polygon_clip( op, gpc_subject, gpc_clip, gpc_result );
for ( int i = 0; i < gpc_result->num_contours; ++i ) {
for ( int j = 0; j < gpc_result->contour[i].num_vertices; j++ ) {
Point3D p( gpc_result->contour[i].vertex[j].x, gpc_result->contour[i].vertex[j].y, -9999.0 );
result.add_node(i, p);
}
result.set_hole_flag( i, gpc_result->hole[i] );
}
make_tg_poly( gpc_result, &result );
// free allocated memory
gpc_free_polygon( gpc_subject );
@ -415,11 +406,89 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
return result;
}
// Generic clipping routine
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const gpc_polygon& clip )
{
TGPolygon result;
gpc_polygon *gpc_subject = new gpc_polygon;
gpc_subject->num_contours = 0;
gpc_subject->contour = NULL;
gpc_subject->hole = NULL;
make_gpc_poly( subject, gpc_subject );
gpc_polygon *gpc_clip = (gpc_polygon*)&clip;
gpc_polygon *gpc_result = new gpc_polygon;
gpc_result->num_contours = 0;
gpc_result->contour = NULL;
gpc_result->hole = NULL;
gpc_op op;
if ( poly_op == POLY_DIFF ) {
op = GPC_DIFF;
} else if ( poly_op == POLY_INT ) {
op = GPC_INT;
} else if ( poly_op == POLY_XOR ) {
op = GPC_XOR;
} else if ( poly_op == POLY_UNION ) {
op = GPC_UNION;
} else {
throw sg_exception("Unknown polygon op, exiting.");
}
gpc_polygon_clip( op, gpc_subject, gpc_clip, gpc_result );
make_tg_poly( gpc_result, &result );
// free allocated memory
gpc_free_polygon( gpc_subject );
gpc_free_polygon( gpc_result );
return result;
}
gpc_polygon polygon_clip_keep_native_fmt( clip_op poly_op, const TGPolygon& subject, const gpc_polygon& clip )
{
gpc_polygon *gpc_subject = new gpc_polygon;
gpc_subject->num_contours = 0;
gpc_subject->contour = NULL;
gpc_subject->hole = NULL;
make_gpc_poly( subject, gpc_subject );
gpc_polygon *gpc_clip = (gpc_polygon*)&clip;
gpc_polygon result;
result.num_contours = 0;
result.contour = NULL;
result.hole = NULL;
gpc_op op;
if ( poly_op == POLY_DIFF ) {
op = GPC_DIFF;
} else if ( poly_op == POLY_INT ) {
op = GPC_INT;
} else if ( poly_op == POLY_XOR ) {
op = GPC_XOR;
} else if ( poly_op == POLY_UNION ) {
op = GPC_UNION;
} else {
throw sg_exception("Unknown polygon op, exiting.");
}
gpc_polygon_clip( op, gpc_subject, gpc_clip, &result );
// free allocated memory
gpc_free_polygon( gpc_subject );
return result;
}
#endif
#ifdef CLIP_CLIPPER
#define FIXEDPT (1000000000000)
#define FIXEDPT (10000000000000)
IntPoint MakeClipperPoint( Point3D pt )
{
@ -451,15 +520,6 @@ void make_clipper_poly( const TGPolygon& in, Polygons *out )
{
// assume contour 0 is boundary, 1..x are holes
// create the boundary
#if 0
SG_LOG(SG_GENERAL, SG_ALERT,
" make_clipper_poly : processing boundary contour, nodes = "
<< in.contour_size(0) << ", hole = "
<< in.get_hole_flag(0)
);
#endif
for (j=0; j<in.contour_size(0); ++j)
{
p = in.get_pt( 0, j );
@ -470,14 +530,6 @@ void make_clipper_poly( const TGPolygon& in, Polygons *out )
// create the holes
for (i=1; i<in.contours(); ++i )
{
#if 0
SG_LOG(SG_GENERAL, SG_ALERT,
" make_clipper_poly : processing hole " << i << ", nodes = "
<< in.contour_size(i) << ", hole = "
<< in.get_hole_flag(i)
);
#endif
contour.clear();
for (j=0; j<in.contour_size(i); ++j)
{
@ -489,6 +541,39 @@ void make_clipper_poly( const TGPolygon& in, Polygons *out )
}
}
void make_tg_poly( const ExPolygons& in, TGPolygon *out )
{
int res_contour = 0;
out->erase();
for (int i=0; i<in.size(); i++)
{
const struct ExPolygon* pg = &in[i];
IntPoint ip;
// Get the boundary contour
for (int j = 0; j < pg->outer.size(); j++)
{
ip = IntPoint( pg->outer[j].X, pg->outer[j].Y );
out->add_node(res_contour, MakeTGPoint(ip));
}
out->set_hole_flag(res_contour, 0);
res_contour++;
// then the holes
for (int j = 0; j < pg->holes.size(); j++)
{
for (int k = 0; k < pg->holes[j].size(); k++)
{
ip = IntPoint( pg->holes[j].at(k).X, pg->holes[j].at(k).Y );
out->add_node(res_contour, MakeTGPoint(ip));
}
out->set_hole_flag(res_contour, 1);
res_contour++;
}
}
}
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const TGPolygon& clip )
{
TGPolygon result;
@ -500,7 +585,6 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const TGPolyg
make_clipper_poly( clip, &clipper_clip );
ExPolygons clipper_result;
//Polygons clipper_result;
ClipType op;
if ( poly_op == POLY_DIFF ) {
@ -520,39 +604,84 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const TGPolyg
c.AddPolygons(clipper_subject, ptSubject);
c.AddPolygons(clipper_clip, ptClip);
Point3D p;
int res_contour = 0;
if (c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd))
{
for (int i=0; i<clipper_result.size(); i++)
{
struct ExPolygon* pg = &clipper_result[i];
IntPoint ip;
c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd);
make_tg_poly( clipper_result, &result );
// Get the boundary contour
for (int j = 0; j < pg->outer.size(); j++)
{
ip = IntPoint( pg->outer[j].X, pg->outer[j].Y );
result.add_node(res_contour, MakeTGPoint(ip));
}
result.set_hole_flag(res_contour, 0);
res_contour++;
return result;
}
// then the holes
for (int j = 0; j < pg->holes.size(); j++)
{
for (int k = 0; k < pg->holes[j].size(); k++)
{
ip = IntPoint( pg->holes[j].at(k).X, pg->holes[j].at(k).Y );
result.add_node(res_contour, MakeTGPoint(ip));
}
result.set_hole_flag(res_contour, 1);
res_contour++;
}
}
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const Polygons& clipper_clip )
{
TGPolygon result;
Polygons clipper_subject;
make_clipper_poly( subject, &clipper_subject );
ExPolygons clipper_result;
ClipType op;
if ( poly_op == POLY_DIFF ) {
op = ctDifference;
} else if ( poly_op == POLY_INT ) {
op = ctIntersection;
} else if ( poly_op == POLY_XOR ) {
op = ctXor;
} else if ( poly_op == POLY_UNION ) {
op = ctUnion;
} else {
throw sg_exception("Unknown polygon op, exiting.");
}
return result;
Clipper c;
c.Clear();
c.AddPolygons(clipper_subject, ptSubject);
c.AddPolygons(clipper_clip, ptClip);
c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd);
make_tg_poly( clipper_result, &result );
return result;
}
Polygons polygon_clip_keep_native_fmt( clip_op poly_op, const TGPolygon& subject, const Polygons& clipper_clip )
{
Polygons clipper_subject;
make_clipper_poly( subject, &clipper_subject );
ExPolygons clipper_result;
Polygons result;
ClipType op;
if ( poly_op == POLY_DIFF ) {
op = ctDifference;
} else if ( poly_op == POLY_INT ) {
op = ctIntersection;
} else if ( poly_op == POLY_XOR ) {
op = ctXor;
} else if ( poly_op == POLY_UNION ) {
op = ctUnion;
} else {
throw sg_exception("Unknown polygon op, exiting.");
}
Clipper c;
c.Clear();
c.AddPolygons(clipper_subject, ptSubject);
c.AddPolygons(clipper_clip, ptClip);
c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd);
// copy contours to polygons structure
for (int i=0; i<clipper_result.size(); i++)
{
result.push_back( clipper_result[i].outer );
for (int j=0; j<clipper_result[i].holes.size(); j++)
{
result.push_back( clipper_result[i].holes[j] );
}
}
return result;
}
#endif
@ -561,6 +690,11 @@ TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_DIFF, subject, clip );
}
TGPolygon tgPolygonDiff( const TGPolygon& subject, const ClipPolyType& clip ) {
return polygon_clip( POLY_DIFF, subject, clip );
}
// Intersection
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_INT, subject, clip );
@ -578,6 +712,10 @@ TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_UNION, subject, clip );
}
ClipPolyType tgPolygonUnion( const TGPolygon& subject, const ClipPolyType& clip ) {
return polygon_clip_keep_native_fmt( POLY_UNION, subject, clip );
}
// canonify the polygon winding, outer contour must be anti-clockwise,
// all inner contours must be clockwise.

View file

@ -29,6 +29,24 @@
# error This library requires C++
#endif
// which clipping lib to use?
//#define CLIP_GPC
#define CLIP_CLIPPER
#ifdef CLIP_GPC
extern "C" {
#include <gpc.h>
}
typedef gpc_polygon ClipPolyType;
#endif
#ifdef CLIP_CLIPPER
#include "clipper.hpp"
using namespace ClipperLib;
typedef Polygons ClipPolyType;
#endif
#include <simgear/compiler.h>
#include <simgear/math/sg_types.hxx>
@ -219,6 +237,7 @@ TGPolygon tgPolygon2tristrip( const TGPolygon& poly );
// Difference
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip );
TGPolygon tgPolygonDiff( const TGPolygon& subject, const ClipPolyType& clip );
// Intersection
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip );
@ -228,6 +247,7 @@ TGPolygon tgPolygonXor( const TGPolygon& subject, const TGPolygon& clip );
// Union
TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip );
ClipPolyType tgPolygonUnion( const TGPolygon& subject, const ClipPolyType& clip );
// Output
std::ostream &operator<< (std::ostream &output, const TGPolygon &poly);