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:
parent
59b534616f
commit
db1a734b19
16 changed files with 253 additions and 98 deletions
|
@ -330,14 +330,11 @@ static TGPolygon calc_elevations( TGAptSurface &surf,
|
||||||
|
|
||||||
void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
||||||
{
|
{
|
||||||
|
ClipPolyType accum;
|
||||||
|
ClipPolyType line_accum;
|
||||||
TGPolygon apt_base;
|
TGPolygon apt_base;
|
||||||
TGPolygon apt_clearing;
|
TGPolygon apt_clearing;
|
||||||
|
|
||||||
TGPolygon accum;
|
|
||||||
accum.erase();
|
|
||||||
TGPolygon line_accum;
|
|
||||||
line_accum.erase();
|
|
||||||
|
|
||||||
// runways
|
// runways
|
||||||
superpoly_list rwy_polys;
|
superpoly_list rwy_polys;
|
||||||
texparams_list rwy_tps;
|
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 );
|
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");
|
SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -112,7 +112,7 @@ void gen_tex_section( const TGPolygon& runway,
|
||||||
const string& material,
|
const string& material,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon *accum ) {
|
ClipPolyType *accum ) {
|
||||||
|
|
||||||
int j, k;
|
int j, k;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,6 @@ void gen_tex_section( const TGPolygon& runway,
|
||||||
const string& material,
|
const string& material,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon *accum );
|
ClipPolyType *accum );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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;
|
TGPolygon base, safe_base;
|
||||||
string material;
|
string material;
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
int BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clearing );
|
int BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clearing );
|
||||||
|
|
||||||
// Build BTG for pavements for airports with no boundary
|
// 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()
|
FeatureList* GetFeatures()
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,7 +79,7 @@ void Helipad::BuildBtg( float alt_m,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
superpoly_list *rwy_lights,
|
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 );
|
SG_LOG( SG_GENERAL, SG_INFO, "Building helipad = " << heli.designator );
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Helipad
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Helipad(char* def);
|
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:
|
private:
|
||||||
struct TGRunway {
|
struct TGRunway {
|
||||||
|
|
|
@ -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 poly;
|
||||||
TGPolygon clipped;
|
TGPolygon clipped;
|
||||||
|
|
|
@ -93,7 +93,7 @@ public:
|
||||||
|
|
||||||
int Finish();
|
int Finish();
|
||||||
int BuildOsg( osg::Group* airport );
|
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:
|
private:
|
||||||
Point3D OffsetPointFirst( Point3D *cur, Point3D *next, double offset_by );
|
Point3D OffsetPointFirst( Point3D *cur, Point3D *next, double offset_by );
|
||||||
|
|
|
@ -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;
|
TGPolygon base, safe_base;
|
||||||
string material;
|
string material;
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int BuildOsg( osg::Group* airport );
|
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:
|
private:
|
||||||
struct TGRunway {
|
struct TGRunway {
|
||||||
|
@ -93,7 +93,7 @@ private:
|
||||||
double &start_pct, double &end_pct,
|
double &start_pct, double &end_pct,
|
||||||
superpoly_list* rwy_polys,
|
superpoly_list* rwy_polys,
|
||||||
texparams_list* texparams,
|
texparams_list* texparams,
|
||||||
TGPolygon* accum );
|
ClipPolyType* accum );
|
||||||
|
|
||||||
// generate the runway overrun area
|
// generate the runway overrun area
|
||||||
void gen_runway_overrun( const TGPolygon& runway_half,
|
void gen_runway_overrun( const TGPolygon& runway_half,
|
||||||
|
@ -101,7 +101,7 @@ private:
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
superpoly_list* rwy_polys,
|
superpoly_list* rwy_polys,
|
||||||
texparams_list* texparams,
|
texparams_list* texparams,
|
||||||
TGPolygon* accum );
|
ClipPolyType* accum );
|
||||||
|
|
||||||
// generate a section of runway
|
// generate a section of runway
|
||||||
void gen_runway_section( const TGPolygon& runway,
|
void gen_runway_section( const TGPolygon& runway,
|
||||||
|
@ -113,14 +113,14 @@ private:
|
||||||
const std::string& material,
|
const std::string& material,
|
||||||
superpoly_list* rwy_polys,
|
superpoly_list* rwy_polys,
|
||||||
texparams_list* texparams,
|
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,
|
void gen_rwy( double alt_m,
|
||||||
const std::string& material,
|
const std::string& material,
|
||||||
superpoly_list* rwy_polys,
|
superpoly_list* rwy_polys,
|
||||||
texparams_list* texparams,
|
texparams_list* texparams,
|
||||||
TGPolygon* accum );
|
ClipPolyType* accum );
|
||||||
|
|
||||||
void gen_rw_marking( const TGPolygon& runway,
|
void gen_rw_marking( const TGPolygon& runway,
|
||||||
double &start1_pct, double &end1_pct,
|
double &start1_pct, double &end1_pct,
|
||||||
|
@ -128,7 +128,7 @@ private:
|
||||||
const string& material,
|
const string& material,
|
||||||
superpoly_list* rwy_polys,
|
superpoly_list* rwy_polys,
|
||||||
texparams_list* texparams,
|
texparams_list* texparams,
|
||||||
TGPolygon* accum, int marking);
|
ClipPolyType* accum, int marking);
|
||||||
|
|
||||||
void gen_runway_lights( float alt_m, superpoly_list* lights );
|
void gen_runway_lights( float alt_m, superpoly_list* lights );
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ void Runway::gen_rw_designation( const string& material,
|
||||||
double &start_pct, double &end_pct,
|
double &start_pct, double &end_pct,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon *accum )
|
ClipPolyType *accum )
|
||||||
{
|
{
|
||||||
if (rwname != "XX"){ /* Do not create a designation block if the runway name is set to none */
|
if (rwname != "XX"){ /* Do not create a designation block if the runway name is set to none */
|
||||||
string letter = "";
|
string letter = "";
|
||||||
|
@ -118,7 +118,7 @@ void Runway::gen_runway_overrun( const TGPolygon& runway_half,
|
||||||
const string& prefix,
|
const string& prefix,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon* accum ) {
|
ClipPolyType* accum ) {
|
||||||
const float length = rwy.length / 2.0 + 2.0 * SG_FEET_TO_METER;
|
const float length = rwy.length / 2.0 + 2.0 * SG_FEET_TO_METER;
|
||||||
double start1_pct = 0.0;
|
double start1_pct = 0.0;
|
||||||
double end1_pct = 0.0;
|
double end1_pct = 0.0;
|
||||||
|
@ -171,7 +171,7 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
||||||
const string& material,
|
const string& material,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon *accum ) {
|
ClipPolyType *accum ) {
|
||||||
gen_tex_section( runway,
|
gen_tex_section( runway,
|
||||||
startl_pct, endl_pct,
|
startl_pct, endl_pct,
|
||||||
startw_pct, endw_pct,
|
startw_pct, endw_pct,
|
||||||
|
|
|
@ -40,7 +40,7 @@ void Runway::gen_rw_marking( const TGPolygon& runway,
|
||||||
const string& material,
|
const string& material,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon *accum, int marking) {
|
ClipPolyType *accum, int marking) {
|
||||||
|
|
||||||
std::vector<sections> rw_marking_list;
|
std::vector<sections> rw_marking_list;
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ void Runway::gen_rwy( double alt_m,
|
||||||
const string& material,
|
const string& material,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon *accum )
|
ClipPolyType *accum )
|
||||||
{
|
{
|
||||||
SG_LOG( SG_GENERAL, SG_INFO, "Building runway = " << rwy.rwnum[0] << " / " << rwy.rwnum[1]);
|
SG_LOG( SG_GENERAL, SG_INFO, "Building runway = " << rwy.rwnum[0] << " / " << rwy.rwnum[1]);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ void Runway::gen_simple_rwy( double alt_m,
|
||||||
const string& material,
|
const string& material,
|
||||||
superpoly_list *rwy_polys,
|
superpoly_list *rwy_polys,
|
||||||
texparams_list *texparams,
|
texparams_list *texparams,
|
||||||
TGPolygon *accum )
|
ClipPolyType *accum )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
@ -26,15 +26,6 @@
|
||||||
// http://www.cs.man.ac.uk/aig/staff/alan/software/
|
// 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/constants.h>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
@ -48,11 +39,6 @@ extern "C" {
|
||||||
#include "polygon.hxx"
|
#include "polygon.hxx"
|
||||||
#include "point2d.hxx"
|
#include "point2d.hxx"
|
||||||
|
|
||||||
#ifdef CLIP_CLIPPER
|
|
||||||
#include "clipper.hpp"
|
|
||||||
using namespace ClipperLib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::endl;
|
using std::endl;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
|
@ -361,6 +347,18 @@ void make_gpc_poly( const TGPolygon& in, gpc_polygon *out ) {
|
||||||
delete [] v_list.vertex;
|
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
|
// Generic clipping routine
|
||||||
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
|
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
|
||||||
const TGPolygon& clip )
|
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 );
|
gpc_polygon_clip( op, gpc_subject, gpc_clip, gpc_result );
|
||||||
|
|
||||||
for ( int i = 0; i < gpc_result->num_contours; ++i ) {
|
make_tg_poly( gpc_result, &result );
|
||||||
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] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// free allocated memory
|
// free allocated memory
|
||||||
gpc_free_polygon( gpc_subject );
|
gpc_free_polygon( gpc_subject );
|
||||||
|
@ -415,11 +406,89 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
|
||||||
|
|
||||||
return result;
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef CLIP_CLIPPER
|
#ifdef CLIP_CLIPPER
|
||||||
|
|
||||||
#define FIXEDPT (1000000000000)
|
#define FIXEDPT (10000000000000)
|
||||||
|
|
||||||
IntPoint MakeClipperPoint( Point3D pt )
|
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
|
// assume contour 0 is boundary, 1..x are holes
|
||||||
// create the boundary
|
// 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)
|
for (j=0; j<in.contour_size(0); ++j)
|
||||||
{
|
{
|
||||||
p = in.get_pt( 0, j );
|
p = in.get_pt( 0, j );
|
||||||
|
@ -470,14 +530,6 @@ void make_clipper_poly( const TGPolygon& in, Polygons *out )
|
||||||
// create the holes
|
// create the holes
|
||||||
for (i=1; i<in.contours(); ++i )
|
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();
|
contour.clear();
|
||||||
for (j=0; j<in.contour_size(i); ++j)
|
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 polygon_clip( clip_op poly_op, const TGPolygon& subject, const TGPolygon& clip )
|
||||||
{
|
{
|
||||||
TGPolygon result;
|
TGPolygon result;
|
||||||
|
@ -500,7 +585,6 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const TGPolyg
|
||||||
make_clipper_poly( clip, &clipper_clip );
|
make_clipper_poly( clip, &clipper_clip );
|
||||||
|
|
||||||
ExPolygons clipper_result;
|
ExPolygons clipper_result;
|
||||||
//Polygons clipper_result;
|
|
||||||
|
|
||||||
ClipType op;
|
ClipType op;
|
||||||
if ( poly_op == POLY_DIFF ) {
|
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_subject, ptSubject);
|
||||||
c.AddPolygons(clipper_clip, ptClip);
|
c.AddPolygons(clipper_clip, ptClip);
|
||||||
|
|
||||||
Point3D p;
|
c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd);
|
||||||
int res_contour = 0;
|
make_tg_poly( clipper_result, &result );
|
||||||
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;
|
|
||||||
|
|
||||||
// Get the boundary contour
|
return result;
|
||||||
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++;
|
|
||||||
|
|
||||||
// then the holes
|
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const Polygons& clipper_clip )
|
||||||
for (int j = 0; j < pg->holes.size(); j++)
|
{
|
||||||
{
|
TGPolygon result;
|
||||||
for (int k = 0; k < pg->holes[j].size(); k++)
|
|
||||||
{
|
Polygons clipper_subject;
|
||||||
ip = IntPoint( pg->holes[j].at(k).X, pg->holes[j].at(k).Y );
|
make_clipper_poly( subject, &clipper_subject );
|
||||||
result.add_node(res_contour, MakeTGPoint(ip));
|
|
||||||
}
|
ExPolygons clipper_result;
|
||||||
result.set_hole_flag(res_contour, 1);
|
|
||||||
res_contour++;
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -561,6 +690,11 @@ TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {
|
||||||
return polygon_clip( POLY_DIFF, subject, clip );
|
return polygon_clip( POLY_DIFF, subject, clip );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TGPolygon tgPolygonDiff( const TGPolygon& subject, const ClipPolyType& clip ) {
|
||||||
|
return polygon_clip( POLY_DIFF, subject, clip );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Intersection
|
// Intersection
|
||||||
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip ) {
|
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip ) {
|
||||||
return polygon_clip( POLY_INT, subject, 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 );
|
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,
|
// canonify the polygon winding, outer contour must be anti-clockwise,
|
||||||
// all inner contours must be clockwise.
|
// all inner contours must be clockwise.
|
||||||
|
|
|
@ -29,6 +29,24 @@
|
||||||
# error This library requires C++
|
# error This library requires C++
|
||||||
#endif
|
#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/compiler.h>
|
||||||
#include <simgear/math/sg_types.hxx>
|
#include <simgear/math/sg_types.hxx>
|
||||||
|
@ -219,6 +237,7 @@ TGPolygon tgPolygon2tristrip( const TGPolygon& poly );
|
||||||
|
|
||||||
// Difference
|
// Difference
|
||||||
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip );
|
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip );
|
||||||
|
TGPolygon tgPolygonDiff( const TGPolygon& subject, const ClipPolyType& clip );
|
||||||
|
|
||||||
// Intersection
|
// Intersection
|
||||||
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip );
|
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip );
|
||||||
|
@ -228,6 +247,7 @@ TGPolygon tgPolygonXor( const TGPolygon& subject, const TGPolygon& clip );
|
||||||
|
|
||||||
// Union
|
// Union
|
||||||
TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip );
|
TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip );
|
||||||
|
ClipPolyType tgPolygonUnion( const TGPolygon& subject, const ClipPolyType& clip );
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
std::ostream &operator<< (std::ostream &output, const TGPolygon &poly);
|
std::ostream &operator<< (std::ostream &output, const TGPolygon &poly);
|
||||||
|
|
Loading…
Reference in a new issue