1
0
Fork 0

Added support for clipper library

- still some issues, but it 'mostly' works
   (change #define in src/lib/polygon to select clipper library)
 - added performance statistics
This commit is contained in:
PSadrozinski 2011-10-10 21:55:40 -04:00 committed by Christian Schmitt
parent 4fb1944964
commit 2e07528da3
6 changed files with 281 additions and 42 deletions

View file

@ -358,6 +358,13 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
double apt_lon = 0.0, apt_lat = 0.0;
int rwy_count = 0;
struct timeval build_start;
struct timeval build_end;
struct timeval cleanup_start;
struct timeval cleanup_end;
struct timeval triangulation_start;
struct timeval triangulation_end;
// Find the average of all the runway long / lats
// TODO : Need runway object...
for (i=0; i<runways.size(); i++)
@ -392,6 +399,9 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
}
}
// Starting to clip the polys
gettimeofday(&build_start, NULL);
// Add the linear features
if (features.size())
{
@ -490,6 +500,11 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
TGPolygon divided_base = tgPolygonSplitLongEdges( filled_base, 200.0 );
TGPolygon base_poly = tgPolygonDiff( divided_base, accum );
gettimeofday(&build_end, NULL);
timersub(&build_end, &build_start, &build_time);
gettimeofday(&cleanup_start, NULL);
// add segments to polygons to remove any possible "T"
// intersections
TGTriNodes tmp_nodes;
@ -632,6 +647,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
line_polys[k].set_poly( poly );
}
SG_LOG(SG_GENERAL, SG_DEBUG, "add nodes base ");
SG_LOG(SG_GENERAL, SG_DEBUG, " before: " << base_poly);
@ -650,6 +666,11 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// write_polygon( base_poly, "base-fin" );
SG_LOG(SG_GENERAL, SG_DEBUG, " after clean up: " << base_poly);
gettimeofday(&cleanup_end, NULL);
timersub(&cleanup_end, &cleanup_start, &cleanup_time);
gettimeofday(&triangulation_start, NULL);
// tesselate the polygons and prepair them for final output
for ( i = 0; i < (int)rwy_polys.size(); ++i )
{
@ -711,6 +732,9 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating base");
TGPolygon base_tris = polygon_tesselate_alt( base_poly );
gettimeofday(&triangulation_end, NULL);
timersub(&triangulation_end, &triangulation_start, &triangulation_time);
//
// We should now have the runway polygons all generated with their
// corresponding triangles and texture coordinates, and the

View file

@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "runway.hxx"
#include "object.hxx"
@ -82,6 +83,21 @@ public:
return icao;
}
void GetBuildTime( struct timeval& tm )
{
tm = build_time;
}
void GetTriangulationTime( struct timeval& tm )
{
tm = triangulation_time;
}
void GetCleanupTime( struct timeval& tm )
{
tm = cleanup_time;
}
void BuildOsg( osg::Group* airport );
void BuildBtg( const string& root, const string_list& elev_src );
@ -101,6 +117,11 @@ private:
SignList signs;
HelipadList helipads;
ClosedPoly* boundary;
// stats
struct timeval build_time;
struct timeval cleanup_time;
struct timeval triangulation_time;
};
typedef std::vector <Airport *> AirportList;

View file

@ -1,3 +1,5 @@
#include <sys/time.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
@ -102,6 +104,12 @@ void Parser::Parse()
char tmp[2048];
bool done = false;
int i;
struct timeval parse_start;
struct timeval parse_end;
struct timeval parse_time;
struct timeval build_time;
struct timeval clean_time;
struct timeval triangulation_time;
ifstream in( filename.c_str() );
if ( !in.is_open() )
@ -114,12 +122,12 @@ void Parser::Parse()
for (i=0; i<parse_positions.size(); i++)
{
SetState(STATE_NONE);
in.clear();
SG_LOG( SG_GENERAL, SG_ALERT, "seeking to " << parse_positions[i] );
in.seekg(parse_positions[i], ios::beg);
gettimeofday(&parse_start, NULL);
while ( !in.eof() && (cur_state != STATE_DONE ) )
{
in.getline(tmp, 2048);
@ -127,15 +135,27 @@ void Parser::Parse()
// Parse the line
ParseLine(tmp);
}
gettimeofday(&parse_end, NULL);
timersub(&parse_end, &parse_start, &parse_time);
// write the airport BTG
if (cur_airport)
{
cur_airport->BuildBtg( work_dir, elevation );
cur_airport->GetBuildTime( build_time );
cur_airport->GetCleanupTime( clean_time );
cur_airport->GetTriangulationTime( triangulation_time );
delete cur_airport;
cur_airport = NULL;
}
SG_LOG( SG_GENERAL, SG_ALERT, "Time to parse " << parse_time.tv_sec << ":" << parse_time.tv_usec );
SG_LOG( SG_GENERAL, SG_ALERT, "Time to build " << build_time.tv_sec << ":" << build_time.tv_usec );
SG_LOG( SG_GENERAL, SG_ALERT, "Time to clean up " << clean_time.tv_sec << ":" << clean_time.tv_usec );
SG_LOG( SG_GENERAL, SG_ALERT, "Time to triangulate " << triangulation_time.tv_sec << ":" << triangulation_time.tv_usec );
}
}

View file

@ -2,15 +2,17 @@
add_library(Polygon STATIC
chop-bin.cxx
clipper.cpp
index.cxx
polygon.cxx
simple_clip.cxx
superpoly.cxx
chop.hxx
clipper.hpp
index.hxx
names.hxx
point2d.hxx
polygon.hxx
simple_clip.hxx
superpoly.hxx
)
)

View file

@ -39,6 +39,11 @@
#include <cstdlib>
#include <ostream>
// TEMP : clipper debugging
#include <simgear/debug/logstream.hxx>
//Workaround for older compilers that don't have std::abs
#if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97) || (defined(_MSC_VER) && _MSC_VER <= 1500)
namespace std
@ -1367,6 +1372,7 @@ void Clipper::SetWindingCount(TEdge &edge)
}
//update windCnt2 ...
if ( IsNonZeroAltFillType(edge) )
{
//nonZero filling ...
@ -1634,6 +1640,7 @@ void Clipper::DeleteFromSEL(TEdge *e)
if( SelPrev ) SelPrev->nextInSEL = SelNext;
else m_SortedEdges = SelNext;
if( SelNext ) SelNext->prevInSEL = SelPrev;
e->nextInSEL = 0;
e->prevInSEL = 0;
}
@ -1915,6 +1922,7 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
//------------------------------------------------------------------------------
OutRec* Clipper::CreateOutRec()
{
OutRec* result = new OutRec;
@ -1930,6 +1938,7 @@ OutRec* Clipper::CreateOutRec()
void Clipper::AddOutPt(TEdge *e, TEdge *altE, const IntPoint &pt)
{
bool ToFront = (e->side == esLeft);
if( e->outIdx < 0 )
{
OutRec *outRec = CreateOutRec();
@ -2210,7 +2219,9 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
if( horzEdge->nextInLML )
{
if( horzEdge->outIdx >= 0 )
{
AddOutPt( horzEdge, 0, IntPoint(horzEdge->xtop, horzEdge->ytop));
}
UpdateEdgeIntoAEL( horzEdge );
}
else
@ -2469,7 +2480,10 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
{
if( IsIntermediate( e, topY ) )
{
if( e->outIdx >= 0 ) AddOutPt(e, 0, IntPoint(e->xtop,e->ytop));
if( e->outIdx >= 0 )
{
AddOutPt(e, 0, IntPoint(e->xtop,e->ytop));
}
UpdateEdgeIntoAEL(e);
//if output polygons share an edge, they'll need joining later ...
@ -2548,6 +2562,7 @@ void Clipper::FixupOutPolygon(OutRec &outRec)
void Clipper::BuildResult(Polygons &polys)
{
int k = 0;
polys.resize(m_PolyOuts.size());
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
{

View file

@ -25,9 +25,16 @@
//
// 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>
@ -41,6 +48,11 @@ extern "C" {
#include "polygon.hxx"
#include "point2d.hxx"
#ifdef CLIP_CLIPPER
#include "clipper.hpp"
using namespace ClipperLib;
#endif
using std::endl;
// Constructor
@ -299,7 +311,15 @@ void TGPolygon::write_contour( const int contour, const string& file ) const {
fclose(fp);
}
// Set operation type
typedef enum {
POLY_DIFF, // Difference
POLY_INT, // Intersection
POLY_XOR, // Exclusive or
POLY_UNION // Union
} clip_op;
#ifdef CLIP_GPC
//
// wrapper functions for gpc polygon clip routines
//
@ -310,9 +330,6 @@ void make_gpc_poly( const TGPolygon& in, gpc_polygon *out ) {
v_list.num_vertices = 0;
v_list.vertex = new gpc_vertex[FG_MAX_VERTICES];
// SG_LOG(SG_GENERAL, SG_DEBUG, "making a gpc_poly");
// SG_LOG(SG_GENERAL, SG_DEBUG, " input contours = " << in.contours());
Point3D p;
// build the gpc_polygon structures
for ( int i = 0; i < in.contours(); ++i ) {
@ -323,6 +340,14 @@ void make_gpc_poly( const TGPolygon& in, gpc_polygon *out ) {
throw sg_exception(message);;
}
#if 0
SG_LOG(SG_GENERAL, SG_ALERT,
" make_clipper_poly : processing contour " << i << ", nodes = "
<< in.contour_size(i) << ", hole = "
<< in.get_hole_flag(i)
);
#endif
for ( int j = 0; j < in.contour_size( i ); ++j ) {
p = in.get_pt( i, j );
v_list.vertex[j].x = p.x();
@ -336,16 +361,6 @@ void make_gpc_poly( const TGPolygon& in, gpc_polygon *out ) {
delete [] v_list.vertex;
}
// Set operation type
typedef enum {
POLY_DIFF, // Difference
POLY_INT, // Intersection
POLY_XOR, // Exclusive or
POLY_UNION // Union
} clip_op;
// Generic clipping routine
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
const TGPolygon& clip )
@ -371,13 +386,13 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
gpc_op op;
if ( poly_op == POLY_DIFF ) {
op = GPC_DIFF;
op = GPC_DIFF;
} else if ( poly_op == POLY_INT ) {
op = GPC_INT;
op = GPC_INT;
} else if ( poly_op == POLY_XOR ) {
op = GPC_XOR;
op = GPC_XOR;
} else if ( poly_op == POLY_UNION ) {
op = GPC_UNION;
op = GPC_UNION;
} else {
throw sg_exception("Unknown polygon op, exiting.");
}
@ -385,29 +400,12 @@ 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 ) {
// SG_LOG(SG_GENERAL, SG_DEBUG,
// " processing contour = " << i << ", nodes = "
// << gpc_result->contour[i].num_vertices << ", hole = "
// << gpc_result->hole[i]);
// sprintf(junkn, "g.%d", junkc++);
// junkfp = fopen(junkn, "w");
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);
}
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 );
// junkp = in_nodes.get_node( index );
// fprintf(junkfp, "%.4f %.4f\n", junkp.x(), junkp.y());
result.add_node(i, p);
// SG_LOG(SG_GENERAL, SG_DEBUG, " - " << index);
}
// fprintf(junkfp, "%.4f %.4f\n",
// gpc_result->contour[i].vertex[0].x,
// gpc_result->contour[i].vertex[0].y);
// fclose(junkfp);
result.set_hole_flag( i, gpc_result->hole[i] );
result.set_hole_flag( i, gpc_result->hole[i] );
}
// free allocated memory
@ -417,7 +415,166 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
return result;
}
#endif
#ifdef CLIP_CLIPPER
#define FIXEDPT (1000000000000)
IntPoint MakeClipperPoint( Point3D pt )
{
long64 x, y;
x = (long64)( pt.x() * FIXEDPT );
y = (long64)( pt.y() * FIXEDPT );
return IntPoint( x, y );
}
Point3D MakeTGPoint( IntPoint pt )
{
double x, y;
x = (double)( ((double)pt.X) / (double)FIXEDPT );
y = (double)( ((double)pt.Y) / (double)FIXEDPT );
return Point3D( x, y, -9999.0f);
}
void make_clipper_poly( const TGPolygon& in, Polygons *out )
{
Polygon contour;
Point3D p;
int i, j;
if (in.contours())
{
// 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 );
contour.push_back(MakeClipperPoint(p));
}
out->push_back(contour);
// 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)
{
p = in.get_pt( i, j );
contour.push_back(MakeClipperPoint(p));
}
out->push_back(contour);
}
}
}
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject, const TGPolygon& clip )
{
TGPolygon result;
Polygons clipper_subject;
make_clipper_poly( subject, &clipper_subject );
Polygons clipper_clip;
make_clipper_poly( clip, &clipper_clip );
//ExPolygons clipper_result;
Polygons 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.");
}
Clipper c;
c.Clear();
c.AddPolygons(clipper_subject, ptSubject);
c.AddPolygons(clipper_clip, ptClip);
Point3D p;
int res_contour = 0;
if (c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd))
{
#if 0 // ExPolygons
for (int i=0; i<clipper_result.size(); i++)
{
struct ExPolygon* pg = &clipper_result[i];
// Get the boundary contour
for (int j = 0; j < pg->outer.size(); j++)
{
p = Point3D( pg->outer[j].X, pg->outer[j].Y, -9999.0 );
result.add_node(res_contour, p);
}
result.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++)
{
p = Point3D( pg->holes[j].at(k).X, pg->holes[j].at(k).Y, -9999.0 );
result.add_node(res_contour, p);
}
result.set_hole_flag(res_contour, 1);
res_contour++;
}
}
#endif
for (int i=0; i<clipper_result.size(); i++)
{
Polygon* pg = &clipper_result[i];
IntPoint ip;
for (int j = 0; j < pg->size(); j++)
{
ip = IntPoint( pg->at(j).X, pg->at(j).Y );
result.add_node(i, MakeTGPoint(ip));
}
if (i==0)
{
result.set_hole_flag(i, 0);
}
else
{
result.set_hole_flag(i, 1);
}
}
}
return result;
}
#endif
// Difference
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {