1
0
Fork 0

- brought in clipper (alternative to gpc)

- moved poly_extra from genapts to polygon library (add intermediate nodes)
- change TGPolyList to arrays of superpolys and texparams in preperation for
generating tex coordinates for line data
This commit is contained in:
PSadrozinski 2012-03-22 09:36:47 +01:00 committed by Christian Schmitt
parent bc3ecf8fe9
commit a6058dff58
11 changed files with 703 additions and 283 deletions

View file

@ -9,7 +9,6 @@ add_executable(genapts
lights.hxx lights.cxx
main.cxx
point2d.cxx point2d.hxx
poly_extra.cxx poly_extra.hxx
runway.cxx runway.hxx
rwy_common.cxx rwy_common.hxx
rwy_nonprec.cxx rwy_nonprec.hxx

View file

@ -48,6 +48,7 @@
#include <simgear/misc/texcoord.hxx>
#include <Geometry/poly_support.hxx>
#include <Geometry/poly_extra.hxx>
#include <Geometry/trinodes.hxx>
#include <Output/output.hxx>
#include <Polygon/chop.hxx>
@ -62,7 +63,6 @@
#include "elevations.hxx"
#include "lights.hxx"
#include "point2d.hxx"
#include "poly_extra.hxx"
#include "runway.hxx"
#include "rwy_common.hxx"
#include "rwy_nonprec.hxx"

View file

@ -26,7 +26,6 @@
#include <simgear/debug/logstream.hxx>
#include "global.hxx"
#include "poly_extra.hxx"
#include "rwy_common.hxx"
#include <stdlib.h>

View file

@ -26,7 +26,6 @@
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include "poly_extra.hxx"
#include "rwy_common.hxx"
#include "rwy_nonprec.hxx"

View file

@ -26,7 +26,6 @@
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include "poly_extra.hxx"
#include "rwy_common.hxx"
#include "taxiway.hxx"

View file

@ -4,6 +4,7 @@ add_library(Geometry STATIC
contour_tree.cxx
line.cxx
poly_support.cxx
poly_extra.cxx
rectangle.cxx
trinodes.cxx
trisegs.cxx
@ -12,6 +13,7 @@ add_library(Geometry STATIC
line.hxx
point3d.hxx
poly_support.hxx
poly_extra.hxx
rectangle.hxx
trinodes.hxx
trisegs.hxx

View file

@ -2,17 +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
clipper.cpp
clipper.hpp
)

View file

@ -25,9 +25,7 @@
//
// http://www.cs.man.ac.uk/aig/staff/alan/software/
//
extern "C" {
#include <gpc.h>
}
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
@ -50,18 +48,15 @@ TGPolygon::TGPolygon( void )
// Destructor
TGPolygon::~TGPolygon( void )
{
TGPolygon::~TGPolygon( void ) {
}
// Set the elevations of points in the current polgyon based on the
// elevations of points in source. For points that are not found in
// source, propogate the value from the nearest matching point.
void TGPolygon::inherit_elevations( const TGPolygon &source )
{
void TGPolygon::inherit_elevations( const TGPolygon &source ) {
TGTriNodes nodes;
nodes.clear();
int i, j;
@ -99,39 +94,43 @@ void TGPolygon::inherit_elevations( const TGPolygon &source )
last = -9999.0;
for ( j = 0; j < (int)poly[i].size(); ++j ) {
Point3D p = poly[i][j];
if ( p.z() > -9000 )
if ( p.z() > -9000 ) {
last = p.z();
else if ( last > -9000 )
} else {
if ( last > -9000 ) {
poly[i][j].setz( last );
}
}
}
// go back ways
last = -9999.0;
for ( j = poly[i].size() - 1; j >= 0; --j ) {
Point3D p = poly[i][j];
if ( p.z() > -9000 )
if ( p.z() > -9000 ) {
last = p.z();
else if ( last > -9000 )
} else {
if ( last > -9000 ) {
poly[i][j].setz( last );
}
}
}
}
}
// Set the elevations of all points to the specified values
void TGPolygon::set_elevations( double elev )
{
for ( unsigned i = 0; i < poly.size(); ++i )
for ( unsigned int j = 0; j < poly[i].size(); ++j )
void TGPolygon::set_elevations( double elev ) {
for ( unsigned i = 0; i < poly.size(); ++i ) {
for ( unsigned int j = 0; j < poly[i].size(); ++j ) {
poly[i][j].setz( elev );
}
}
}
// Calculate theta of angle (a, b, c)
double tgPolygonCalcAngle(point2d a, point2d b, point2d c)
{
double tgPolygonCalcAngle(point2d a, point2d b, point2d c) {
point2d u, v;
double udist, vdist, uv_dot, tmp;
@ -163,8 +162,7 @@ double tgPolygonCalcAngle(point2d a, point2d b, point2d c)
// negative areas indicate counter clockwise winding
// positive areas indicate clockwise winding.
double TGPolygon::area_contour( const int contour ) const
{
double TGPolygon::area_contour( const int contour ) const {
// area = 1/2 * sum[i = 0 to k-1][x(i)*y(i+1) - x(i+1)*y(i)]
// where i=k is defined as i=0
@ -172,8 +170,9 @@ double TGPolygon::area_contour( const int contour ) const
int size = c.size();
double sum = 0.0;
for ( int i = 0; i < size; ++i )
for ( int i = 0; i < size; ++i ) {
sum += c[(i+1)%size].x() * c[i].y() - c[i].x() * c[(i+1)%size].y();
}
// area can be negative or positive depending on the polygon
// winding order
@ -182,8 +181,7 @@ double TGPolygon::area_contour( const int contour ) const
// return the smallest interior angle of the contour
double TGPolygon::minangle_contour( const int contour )
{
double TGPolygon::minangle_contour( const int contour ) {
point_list c = poly[contour];
int size = c.size();
int p1_index, p2_index, p3_index;
@ -193,14 +191,16 @@ double TGPolygon::minangle_contour( const int contour )
for ( int i = 0; i < size; ++i ) {
p1_index = i - 1;
if ( p1_index < 0 )
if ( p1_index < 0 ) {
p1_index += size;
}
p2_index = i;
p3_index = i + 1;
if ( p3_index >= size )
if ( p3_index >= size ) {
p3_index -= size;
}
p1.x = c[p1_index].x();
p1.y = c[p1_index].y();
@ -213,21 +213,20 @@ double TGPolygon::minangle_contour( const int contour )
angle = tgPolygonCalcAngle( p1, p2, p3 );
if ( angle < min_angle )
if ( angle < min_angle ) {
min_angle = angle;
}
}
return min_angle;
}
// return true if contour A is inside countour B
bool TGPolygon::is_inside( int a, int b ) const
{
bool TGPolygon::is_inside( int a, int b ) const {
// make polygons from each specified contour
TGPolygon A, B;
point_list pl;
A.erase();
B.erase();
@ -249,9 +248,10 @@ bool TGPolygon::is_inside( int a, int b ) const
// char junk;
// cin >> junk;
if ( result.contours() == 0 )
if ( result.contours() == 0 ) {
// SG_LOG(SG_GENERAL, SG_DEBUG, " " << a << " is_inside() " << b);
return true;
}
// SG_LOG(SG_GENERAL, SG_DEBUG, " " << a << " not is_inside() " << b);
return false;
@ -259,8 +259,7 @@ bool TGPolygon::is_inside( int a, int b ) const
// shift every point in the polygon by lon, lat
void TGPolygon::shift( double lon, double lat )
{
void TGPolygon::shift( double lon, double lat ) {
for ( int i = 0; i < (int)poly.size(); ++i ) {
for ( int j = 0; j < (int)poly[i].size(); ++j ) {
poly[i][j].setx( poly[i][j].x() + lon );
@ -271,15 +270,15 @@ void TGPolygon::shift( double lon, double lat )
// output
void TGPolygon::write( const string& file ) const
{
void TGPolygon::write( const string& file ) const {
FILE *fp = fopen( file.c_str(), "w" );
fprintf(fp, "%d\n", poly.size());
for ( int i = 0; i < (int)poly.size(); ++i ) {
fprintf(fp, "%d\n", poly[i].size());
for ( int j = 0; j < (int)poly[i].size(); ++j )
for ( int j = 0; j < (int)poly[i].size(); ++j ) {
fprintf(fp, "%.6f %.6f\n", poly[i][j].x(), poly[i][j].y());
}
fprintf(fp, "%.6f %.6f\n", poly[i][0].x(), poly[i][0].y());
}
@ -288,32 +287,35 @@ void TGPolygon::write( const string& file ) const
// output
void TGPolygon::write_contour( const int contour, const string& file ) const
{
void TGPolygon::write_contour( const int contour, const string& file ) const {
FILE *fp = fopen( file.c_str(), "w" );
for ( int j = 0; j < (int)poly[contour].size(); ++j )
for ( int j = 0; j < (int)poly[contour].size(); ++j ) {
fprintf(fp, "%.6f %.6f\n", poly[contour][j].x(), poly[contour][j].y());
}
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
//
// Make a gpc_poly from an TGPolygon
void make_gpc_poly( const TGPolygon& in, gpc_polygon *out )
{
void make_gpc_poly( const TGPolygon& in, gpc_polygon *out ) {
gpc_vertex_list v_list;
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 ) {
@ -324,6 +326,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();
@ -337,15 +347,17 @@ 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);
}
// Set operation type
typedef enum {
POLY_DIFF, // Difference
POLY_INT, // Intersection
POLY_XOR, // Exclusive or
POLY_UNION // Union
} clip_op;
out->set_hole_flag( i, in->hole[i] );
}
}
// Generic clipping routine
TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
@ -354,7 +366,6 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
TGPolygon result;
gpc_polygon *gpc_subject = new gpc_polygon;
gpc_subject->num_contours = 0;
gpc_subject->contour = NULL;
gpc_subject->hole = NULL;
@ -372,44 +383,21 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
gpc_result->hole = NULL;
gpc_op op;
if ( poly_op == POLY_DIFF )
if ( poly_op == POLY_DIFF ) {
op = GPC_DIFF;
else if ( poly_op == POLY_INT )
} else if ( poly_op == POLY_INT ) {
op = GPC_INT;
else if ( poly_op == POLY_XOR )
} else if ( poly_op == POLY_XOR ) {
op = GPC_XOR;
else if ( poly_op == POLY_UNION )
} else if ( poly_op == POLY_UNION ) {
op = GPC_UNION;
else
} else {
throw sg_exception("Unknown polygon op, exiting.");
}
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 );
// 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] );
}
make_tg_poly( gpc_result, &result );
// free allocated memory
gpc_free_polygon( gpc_subject );
@ -419,40 +407,323 @@ 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 (10000000000000)
#define FIXEDPT (10000000000000000)
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
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 )
{
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);
}
}
}
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;
Polygons clipper_subject;
make_clipper_poly( subject, &clipper_subject );
Polygons clipper_clip;
make_clipper_poly( clip, &clipper_clip );
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.");
}
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;
}
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.");
}
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
// Difference
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip )
{
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_DIFF, subject, clip );
}
#if CLIP_NATIVE
TGPolygon tgPolygonDiff( const TGPolygon& subject, const ClipPolyType& clip ) {
return polygon_clip( POLY_DIFF, subject, clip );
}
#endif
// Intersection
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip )
{
TGPolygon tgPolygonInt( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_INT, subject, clip );
}
// Exclusive or
TGPolygon tgPolygonXor( const TGPolygon& subject, const TGPolygon& clip )
{
TGPolygon tgPolygonXor( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_XOR, subject, clip );
}
// Union
TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip )
{
TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_UNION, subject, clip );
}
#if CLIP_NATIVE
ClipPolyType tgPolygonUnion( const TGPolygon& subject, const ClipPolyType& clip ) {
return polygon_clip_keep_native_fmt( POLY_UNION, subject, clip );
}
#endif
// canonify the polygon winding, outer contour must be anti-clockwise,
// all inner contours must be clockwise.
TGPolygon polygon_canonify( const TGPolygon& in_poly )
{
TGPolygon polygon_canonify( const TGPolygon& in_poly ) {
TGPolygon result;
result.erase();
// Negative areas indicate counter clockwise winding. Postitive
@ -473,19 +744,22 @@ TGPolygon polygon_canonify( const TGPolygon& in_poly )
// reverse contour
point_list rcontour;
rcontour.clear();
for ( int j = (int)contour.size() - 1; j >= 0; --j )
for ( int j = (int)contour.size() - 1; j >= 0; --j ) {
rcontour.push_back( contour[j] );
}
result.add_contour( rcontour, hole_flag );
} else if ( !hole_flag && (area > 0) ) {
// reverse contour
point_list rcontour;
rcontour.clear();
for ( int j = (int)contour.size() - 1; j >= 0; --j )
for ( int j = (int)contour.size() - 1; j >= 0; --j ) {
rcontour.push_back( contour[j] );
}
result.add_contour( rcontour, hole_flag );
} else
} else {
result.add_contour( contour, hole_flag );
}
}
return result;
}
@ -493,8 +767,7 @@ TGPolygon polygon_canonify( const TGPolygon& in_poly )
// Traverse a polygon and split edges until they are less than max_len
// (specified in meters)
TGPolygon tgPolygonSplitLongEdges( const TGPolygon &poly, double max_len )
{
TGPolygon tgPolygonSplitLongEdges( const TGPolygon &poly, double max_len ) {
TGPolygon result;
Point3D p0, p1;
int i, j, k;
@ -510,7 +783,8 @@ TGPolygon tgPolygonSplitLongEdges( const TGPolygon &poly, double max_len )
SG_LOG(SG_GENERAL, SG_DEBUG, " " << p0 << " - " << p1);
if ( fabs(p0.y()) < (90.0 - SG_EPSILON)
|| fabs(p1.y()) < (90.0 - SG_EPSILON) ) {
|| fabs(p1.y()) < (90.0 - SG_EPSILON) )
{
double az1, az2, s;
geo_inverse_wgs_84( 0.0,
p0.y(), p0.x(), p1.y(), p1.x(),
@ -577,8 +851,7 @@ TGPolygon tgPolygonSplitLongEdges( const TGPolygon &poly, double max_len )
// Traverse a polygon and return the union of all the non-hole contours
TGPolygon tgPolygonStripHoles( const TGPolygon &poly )
{
TGPolygon tgPolygonStripHoles( const TGPolygon &poly ) {
TGPolygon result; result.erase();
SG_LOG(SG_GENERAL, SG_DEBUG, "strip_out_holes()");
@ -596,20 +869,163 @@ TGPolygon tgPolygonStripHoles( const TGPolygon &poly )
return result;
}
#if 0
// Wrapper for the fast Polygon Triangulation based on Seidel's
// Algorithm by Atul Narkhede and Dinesh Manocha
// http://www.cs.unc.edu/~dm/CODE/GEM/chapter.html
// I make this oversize because given an n sided concave polygon with
// m, n, o, ... sided holes, I have no idea how many triangles would
// result and I don't have time right now to see if an upper bound can
// be determined easily.
#define FG_MAX_TRIANGLES 100000
TGPolygon polygon_to_tristrip( const TGPolygon& in_poly ) {
int i, j;
// canonify the polygon winding, outer contour must be
// anti-clockwise, all inner contours must be clockwise.
TGPolygon canon_poly = polygon_canonify( in_poly );
// create and fill in the required structures
int ncontours = canon_poly.contours();
int cntr[ncontours];
int vsize = 1;
for ( i = 0; i < canon_poly.contours(); ++i ) {
cntr[i] = canon_poly.contour_size( i );
vsize += cntr[i];
}
double vertices[vsize][2];
int counter = 1;
Point3D p;
for ( i = 0; i < canon_poly.contours(); ++i ) {
for ( j = 0; j < canon_poly.contour_size( i ); ++j ) {
p = canon_poly.get_pt( i, j );
vertices[counter][0] = p.x();
vertices[counter][1] = p.y();
counter++;
}
}
int triangles[FG_MAX_TRIANGLES][3];
// do the triangulation
int ntriangles = triangulate_polygon(ncontours, cntr, vertices, triangles);
/*
gpc_polygon *tmp_poly = new gpc_polygon;
tmp_poly->num_contours = 0;
tmp_poly->contour = NULL;
tmp_poly->hole = NULL;
make_gpc_poly( in_poly, tmp_poly );
gpc_tristrip *tmp_tristrip = new gpc_tristrip;
tmp_tristrip->num_strips = 0;
tmp_tristrip->strip = NULL;
gpc_polygon_to_tristrip( tmp_poly, tmp_tristrip );
TGPolygon result;
for ( int i = 0; i < tmp_tristrip->num_strips; ++i ) {
SG_LOG(SG_GENERAL, SG_DEBUG, " processing strip = "
<< i << ", nodes = "
<< tmp_tristrip->strip[i].num_vertices);
// sprintf(junkn, "g.%d", junkc++);
// junkfp = fopen(junkn, "w");
for ( int j = 0; j < tmp_tristrip->strip[i].num_vertices; j++ ) {
Point3D p( tmp_tristrip->strip[i].vertex[j].x,
tmp_tristrip->strip[i].vertex[j].y,
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);
}
// free allocated memory
gpc_free_polygon( tmp_poly );
gpc_free_tristrip( tmp_tristrip );
*/
// return result;
}
#endif
#if 0
//
// wrapper functions for gpc polygon to tristrip routine
//
TGPolygon polygon_to_tristrip_old( const TGPolygon& in_poly ) {
gpc_polygon *tmp_poly = new gpc_polygon;
tmp_poly->num_contours = 0;
tmp_poly->contour = NULL;
tmp_poly->hole = NULL;
make_gpc_poly( in_poly, tmp_poly );
gpc_tristrip *tmp_tristrip = new gpc_tristrip;
tmp_tristrip->num_strips = 0;
tmp_tristrip->strip = NULL;
gpc_polygon_to_tristrip( tmp_poly, tmp_tristrip );
TGPolygon result;
for ( int i = 0; i < tmp_tristrip->num_strips; ++i ) {
SG_LOG(SG_GENERAL, SG_DEBUG, " processing strip = "
<< i << ", nodes = "
<< tmp_tristrip->strip[i].num_vertices);
// sprintf(junkn, "g.%d", junkc++);
// junkfp = fopen(junkn, "w");
for ( int j = 0; j < tmp_tristrip->strip[i].num_vertices; j++ ) {
Point3D p( tmp_tristrip->strip[i].vertex[j].x,
tmp_tristrip->strip[i].vertex[j].y,
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);
}
// free allocated memory
gpc_free_polygon( tmp_poly );
gpc_free_tristrip( tmp_tristrip );
return result;
}
#endif
// Send a polygon to standard output.
ostream &
operator<< (ostream &output, const TGPolygon &poly)
{
int nContours = poly.contours();
output << nContours << endl;
for (int i = 0; i < nContours; i++) {
int nPoints = poly.contour_size(i);
output << nPoints << endl;
output << poly.get_hole_flag(i) << endl;
for (int j = 0; j < nPoints; j++)
for (int j = 0; j < nPoints; j++) {
output << poly.get_pt(i, j) << endl;
}
}
return output; // MSVC
}

View file

@ -29,12 +29,26 @@
# error This library requires C++
#endif
#include <simgear/compiler.h>
#include <simgear/math/sg_types.hxx>
#include <Geometry/point3d.hxx>
#include <iostream>
#include <string>
#include <vector>
#include "point2d.hxx"
/* which clipping lib to use? Looks like we should go with clipper
* It appears to be both faster and generates better accuracy
*/
//#define CLIP_GPC
#define CLIP_CLIPPER
// forward declaration
class TGPolygon;
#define CLIP_GPC
// #define CLIP_CLIPPER
/* Set to 1 to allow keeping accum poly in native clipping lib format
* Although it seems to work on some airports, EHAM is pretty broken
@ -50,6 +64,8 @@ extern "C" {
#if CLIP_NATIVE // optimization apparently causing errors
typedef gpc_polygon ClipPolyType;
#else
typedef TGPolygon ClipPolyType;
#endif
#endif /* CLIP_GPC */
@ -60,19 +76,13 @@ using namespace ClipperLib;
#if CLIP_NATIVE // optimization apparently causing errors
typedef Polygons ClipPolyType;
#else
typedef TGPolygon ClipPolyType;
#endif
#endif /* CLIP_CLIPPER */
#include <simgear/compiler.h>
#include <simgear/math/sg_types.hxx>
#include <Geometry/point3d.hxx>
#include <iostream>
#include <string>
#include <vector>
#include "point2d.hxx"
#define FG_MAX_VERTICES 1500000
@ -238,10 +248,6 @@ void write_contour( const int contour, const std::string& file ) const;
};
#if !CLIP_NATIVE
typedef TGPolygon ClipPolyType;
#endif
typedef std::vector < TGPolygon > poly_list;
typedef poly_list::iterator poly_list_iterator;
typedef poly_list::const_iterator const_poly_list_iterator;