- 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:
parent
bc3ecf8fe9
commit
a6058dff58
11 changed files with 703 additions and 283 deletions
|
@ -9,7 +9,6 @@ add_executable(genapts
|
||||||
lights.hxx lights.cxx
|
lights.hxx lights.cxx
|
||||||
main.cxx
|
main.cxx
|
||||||
point2d.cxx point2d.hxx
|
point2d.cxx point2d.hxx
|
||||||
poly_extra.cxx poly_extra.hxx
|
|
||||||
runway.cxx runway.hxx
|
runway.cxx runway.hxx
|
||||||
rwy_common.cxx rwy_common.hxx
|
rwy_common.cxx rwy_common.hxx
|
||||||
rwy_nonprec.cxx rwy_nonprec.hxx
|
rwy_nonprec.cxx rwy_nonprec.hxx
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include <simgear/misc/texcoord.hxx>
|
#include <simgear/misc/texcoord.hxx>
|
||||||
|
|
||||||
#include <Geometry/poly_support.hxx>
|
#include <Geometry/poly_support.hxx>
|
||||||
|
#include <Geometry/poly_extra.hxx>
|
||||||
#include <Geometry/trinodes.hxx>
|
#include <Geometry/trinodes.hxx>
|
||||||
#include <Output/output.hxx>
|
#include <Output/output.hxx>
|
||||||
#include <Polygon/chop.hxx>
|
#include <Polygon/chop.hxx>
|
||||||
|
@ -62,7 +63,6 @@
|
||||||
#include "elevations.hxx"
|
#include "elevations.hxx"
|
||||||
#include "lights.hxx"
|
#include "lights.hxx"
|
||||||
#include "point2d.hxx"
|
#include "point2d.hxx"
|
||||||
#include "poly_extra.hxx"
|
|
||||||
#include "runway.hxx"
|
#include "runway.hxx"
|
||||||
#include "rwy_common.hxx"
|
#include "rwy_common.hxx"
|
||||||
#include "rwy_nonprec.hxx"
|
#include "rwy_nonprec.hxx"
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
#include "global.hxx"
|
#include "global.hxx"
|
||||||
#include "poly_extra.hxx"
|
|
||||||
#include "rwy_common.hxx"
|
#include "rwy_common.hxx"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
#include "poly_extra.hxx"
|
|
||||||
#include "rwy_common.hxx"
|
#include "rwy_common.hxx"
|
||||||
#include "rwy_nonprec.hxx"
|
#include "rwy_nonprec.hxx"
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
#include "poly_extra.hxx"
|
|
||||||
#include "rwy_common.hxx"
|
#include "rwy_common.hxx"
|
||||||
#include "taxiway.hxx"
|
#include "taxiway.hxx"
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ add_library(Geometry STATIC
|
||||||
contour_tree.cxx
|
contour_tree.cxx
|
||||||
line.cxx
|
line.cxx
|
||||||
poly_support.cxx
|
poly_support.cxx
|
||||||
|
poly_extra.cxx
|
||||||
rectangle.cxx
|
rectangle.cxx
|
||||||
trinodes.cxx
|
trinodes.cxx
|
||||||
trisegs.cxx
|
trisegs.cxx
|
||||||
|
@ -12,6 +13,7 @@ add_library(Geometry STATIC
|
||||||
line.hxx
|
line.hxx
|
||||||
point3d.hxx
|
point3d.hxx
|
||||||
poly_support.hxx
|
poly_support.hxx
|
||||||
|
poly_extra.hxx
|
||||||
rectangle.hxx
|
rectangle.hxx
|
||||||
trinodes.hxx
|
trinodes.hxx
|
||||||
trisegs.hxx
|
trisegs.hxx
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
|
|
||||||
add_library(Polygon STATIC
|
add_library(Polygon STATIC
|
||||||
chop-bin.cxx
|
chop-bin.cxx
|
||||||
clipper.cpp
|
|
||||||
index.cxx
|
index.cxx
|
||||||
polygon.cxx
|
polygon.cxx
|
||||||
simple_clip.cxx
|
simple_clip.cxx
|
||||||
superpoly.cxx
|
superpoly.cxx
|
||||||
chop.hxx
|
chop.hxx
|
||||||
clipper.hpp
|
|
||||||
index.hxx
|
index.hxx
|
||||||
names.hxx
|
names.hxx
|
||||||
point2d.hxx
|
point2d.hxx
|
||||||
polygon.hxx
|
polygon.hxx
|
||||||
simple_clip.hxx
|
simple_clip.hxx
|
||||||
superpoly.hxx
|
superpoly.hxx
|
||||||
|
clipper.cpp
|
||||||
|
clipper.hpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,9 +25,7 @@
|
||||||
//
|
//
|
||||||
// http://www.cs.man.ac.uk/aig/staff/alan/software/
|
// http://www.cs.man.ac.uk/aig/staff/alan/software/
|
||||||
//
|
//
|
||||||
extern "C" {
|
|
||||||
#include <gpc.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
@ -50,18 +48,15 @@ TGPolygon::TGPolygon( void )
|
||||||
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
TGPolygon::~TGPolygon( void )
|
TGPolygon::~TGPolygon( void ) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set the elevations of points in the current polgyon based on the
|
// Set the elevations of points in the current polgyon based on the
|
||||||
// elevations of points in source. For points that are not found in
|
// elevations of points in source. For points that are not found in
|
||||||
// source, propogate the value from the nearest matching point.
|
// 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;
|
TGTriNodes nodes;
|
||||||
|
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -99,39 +94,43 @@ void TGPolygon::inherit_elevations( const TGPolygon &source )
|
||||||
last = -9999.0;
|
last = -9999.0;
|
||||||
for ( j = 0; j < (int)poly[i].size(); ++j ) {
|
for ( j = 0; j < (int)poly[i].size(); ++j ) {
|
||||||
Point3D p = poly[i][j];
|
Point3D p = poly[i][j];
|
||||||
if ( p.z() > -9000 )
|
if ( p.z() > -9000 ) {
|
||||||
last = p.z();
|
last = p.z();
|
||||||
else if ( last > -9000 )
|
} else {
|
||||||
|
if ( last > -9000 ) {
|
||||||
poly[i][j].setz( last );
|
poly[i][j].setz( last );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// go back ways
|
// go back ways
|
||||||
last = -9999.0;
|
last = -9999.0;
|
||||||
for ( j = poly[i].size() - 1; j >= 0; --j ) {
|
for ( j = poly[i].size() - 1; j >= 0; --j ) {
|
||||||
Point3D p = poly[i][j];
|
Point3D p = poly[i][j];
|
||||||
if ( p.z() > -9000 )
|
if ( p.z() > -9000 ) {
|
||||||
last = p.z();
|
last = p.z();
|
||||||
else if ( last > -9000 )
|
} else {
|
||||||
|
if ( last > -9000 ) {
|
||||||
poly[i][j].setz( last );
|
poly[i][j].setz( last );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set the elevations of all points to the specified values
|
// Set the elevations of all points to the specified values
|
||||||
void TGPolygon::set_elevations( double elev )
|
void TGPolygon::set_elevations( double elev ) {
|
||||||
{
|
for ( unsigned i = 0; i < poly.size(); ++i ) {
|
||||||
for ( unsigned i = 0; i < poly.size(); ++i )
|
for ( unsigned int j = 0; j < poly[i].size(); ++j ) {
|
||||||
for ( unsigned int j = 0; j < poly[i].size(); ++j )
|
|
||||||
poly[i][j].setz( elev );
|
poly[i][j].setz( elev );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Calculate theta of angle (a, b, c)
|
// 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;
|
point2d u, v;
|
||||||
double udist, vdist, uv_dot, tmp;
|
double udist, vdist, uv_dot, tmp;
|
||||||
|
|
||||||
|
@ -163,8 +162,7 @@ double tgPolygonCalcAngle(point2d a, point2d b, point2d c)
|
||||||
// negative areas indicate counter clockwise winding
|
// negative areas indicate counter clockwise winding
|
||||||
// positive areas indicate 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)]
|
// 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
|
// where i=k is defined as i=0
|
||||||
|
|
||||||
|
@ -172,8 +170,9 @@ double TGPolygon::area_contour( const int contour ) const
|
||||||
int size = c.size();
|
int size = c.size();
|
||||||
double sum = 0.0;
|
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();
|
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
|
// area can be negative or positive depending on the polygon
|
||||||
// winding order
|
// winding order
|
||||||
|
@ -182,8 +181,7 @@ double TGPolygon::area_contour( const int contour ) const
|
||||||
|
|
||||||
|
|
||||||
// return the smallest interior angle of the contour
|
// 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];
|
point_list c = poly[contour];
|
||||||
int size = c.size();
|
int size = c.size();
|
||||||
int p1_index, p2_index, p3_index;
|
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 ) {
|
for ( int i = 0; i < size; ++i ) {
|
||||||
p1_index = i - 1;
|
p1_index = i - 1;
|
||||||
if ( p1_index < 0 )
|
if ( p1_index < 0 ) {
|
||||||
p1_index += size;
|
p1_index += size;
|
||||||
|
}
|
||||||
|
|
||||||
p2_index = i;
|
p2_index = i;
|
||||||
|
|
||||||
p3_index = i + 1;
|
p3_index = i + 1;
|
||||||
if ( p3_index >= size )
|
if ( p3_index >= size ) {
|
||||||
p3_index -= size;
|
p3_index -= size;
|
||||||
|
}
|
||||||
|
|
||||||
p1.x = c[p1_index].x();
|
p1.x = c[p1_index].x();
|
||||||
p1.y = c[p1_index].y();
|
p1.y = c[p1_index].y();
|
||||||
|
@ -213,21 +213,20 @@ double TGPolygon::minangle_contour( const int contour )
|
||||||
|
|
||||||
angle = tgPolygonCalcAngle( p1, p2, p3 );
|
angle = tgPolygonCalcAngle( p1, p2, p3 );
|
||||||
|
|
||||||
if ( angle < min_angle )
|
if ( angle < min_angle ) {
|
||||||
min_angle = angle;
|
min_angle = angle;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return min_angle;
|
return min_angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return true if contour A is inside countour B
|
// 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
|
// make polygons from each specified contour
|
||||||
TGPolygon A, B;
|
TGPolygon A, B;
|
||||||
point_list pl;
|
point_list pl;
|
||||||
|
|
||||||
A.erase();
|
A.erase();
|
||||||
B.erase();
|
B.erase();
|
||||||
|
|
||||||
|
@ -249,9 +248,10 @@ bool TGPolygon::is_inside( int a, int b ) const
|
||||||
// char junk;
|
// char junk;
|
||||||
// cin >> junk;
|
// cin >> junk;
|
||||||
|
|
||||||
if ( result.contours() == 0 )
|
if ( result.contours() == 0 ) {
|
||||||
// SG_LOG(SG_GENERAL, SG_DEBUG, " " << a << " is_inside() " << b);
|
// SG_LOG(SG_GENERAL, SG_DEBUG, " " << a << " is_inside() " << b);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// SG_LOG(SG_GENERAL, SG_DEBUG, " " << a << " not is_inside() " << b);
|
// SG_LOG(SG_GENERAL, SG_DEBUG, " " << a << " not is_inside() " << b);
|
||||||
return false;
|
return false;
|
||||||
|
@ -259,8 +259,7 @@ bool TGPolygon::is_inside( int a, int b ) const
|
||||||
|
|
||||||
|
|
||||||
// shift every point in the polygon by lon, lat
|
// 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 i = 0; i < (int)poly.size(); ++i ) {
|
||||||
for ( int j = 0; j < (int)poly[i].size(); ++j ) {
|
for ( int j = 0; j < (int)poly[i].size(); ++j ) {
|
||||||
poly[i][j].setx( poly[i][j].x() + lon );
|
poly[i][j].setx( poly[i][j].x() + lon );
|
||||||
|
@ -271,15 +270,15 @@ void TGPolygon::shift( double lon, double lat )
|
||||||
|
|
||||||
|
|
||||||
// output
|
// output
|
||||||
void TGPolygon::write( const string& file ) const
|
void TGPolygon::write( const string& file ) const {
|
||||||
{
|
|
||||||
FILE *fp = fopen( file.c_str(), "w" );
|
FILE *fp = fopen( file.c_str(), "w" );
|
||||||
|
|
||||||
fprintf(fp, "%d\n", poly.size());
|
fprintf(fp, "%d\n", poly.size());
|
||||||
for ( int i = 0; i < (int)poly.size(); ++i ) {
|
for ( int i = 0; i < (int)poly.size(); ++i ) {
|
||||||
fprintf(fp, "%d\n", poly[i].size());
|
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][j].x(), poly[i][j].y());
|
||||||
|
}
|
||||||
fprintf(fp, "%.6f %.6f\n", poly[i][0].x(), poly[i][0].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
|
// 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" );
|
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());
|
fprintf(fp, "%.6f %.6f\n", poly[contour][j].x(), poly[contour][j].y());
|
||||||
|
}
|
||||||
|
|
||||||
fclose(fp);
|
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
|
// wrapper functions for gpc polygon clip routines
|
||||||
//
|
//
|
||||||
|
|
||||||
// Make a gpc_poly from an TGPolygon
|
// 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;
|
gpc_vertex_list v_list;
|
||||||
|
|
||||||
v_list.num_vertices = 0;
|
v_list.num_vertices = 0;
|
||||||
v_list.vertex = new gpc_vertex[FG_MAX_VERTICES];
|
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;
|
Point3D p;
|
||||||
// build the gpc_polygon structures
|
// build the gpc_polygon structures
|
||||||
for ( int i = 0; i < in.contours(); ++i ) {
|
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);;
|
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 ) {
|
for ( int j = 0; j < in.contour_size( i ); ++j ) {
|
||||||
p = in.get_pt( i, j );
|
p = in.get_pt( i, j );
|
||||||
v_list.vertex[j].x = p.x();
|
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;
|
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
|
out->set_hole_flag( i, in->hole[i] );
|
||||||
typedef enum {
|
}
|
||||||
POLY_DIFF, // Difference
|
}
|
||||||
POLY_INT, // Intersection
|
|
||||||
POLY_XOR, // Exclusive or
|
|
||||||
POLY_UNION // Union
|
|
||||||
} clip_op;
|
|
||||||
|
|
||||||
|
|
||||||
// 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,
|
||||||
|
@ -354,7 +366,6 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
|
||||||
TGPolygon result;
|
TGPolygon result;
|
||||||
|
|
||||||
gpc_polygon *gpc_subject = new gpc_polygon;
|
gpc_polygon *gpc_subject = new gpc_polygon;
|
||||||
|
|
||||||
gpc_subject->num_contours = 0;
|
gpc_subject->num_contours = 0;
|
||||||
gpc_subject->contour = NULL;
|
gpc_subject->contour = NULL;
|
||||||
gpc_subject->hole = NULL;
|
gpc_subject->hole = NULL;
|
||||||
|
@ -372,44 +383,21 @@ TGPolygon polygon_clip( clip_op poly_op, const TGPolygon& subject,
|
||||||
gpc_result->hole = NULL;
|
gpc_result->hole = NULL;
|
||||||
|
|
||||||
gpc_op op;
|
gpc_op op;
|
||||||
if ( poly_op == POLY_DIFF )
|
if ( poly_op == POLY_DIFF ) {
|
||||||
op = GPC_DIFF;
|
op = GPC_DIFF;
|
||||||
else if ( poly_op == POLY_INT )
|
} else if ( poly_op == POLY_INT ) {
|
||||||
op = GPC_INT;
|
op = GPC_INT;
|
||||||
else if ( poly_op == POLY_XOR )
|
} else if ( poly_op == POLY_XOR ) {
|
||||||
op = GPC_XOR;
|
op = GPC_XOR;
|
||||||
else if ( poly_op == POLY_UNION )
|
} else if ( poly_op == POLY_UNION ) {
|
||||||
op = GPC_UNION;
|
op = GPC_UNION;
|
||||||
else
|
} else {
|
||||||
throw sg_exception("Unknown polygon op, exiting.");
|
throw sg_exception("Unknown polygon op, exiting.");
|
||||||
|
}
|
||||||
|
|
||||||
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 );
|
||||||
// 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] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// free allocated memory
|
// free allocated memory
|
||||||
gpc_free_polygon( gpc_subject );
|
gpc_free_polygon( gpc_subject );
|
||||||
|
@ -419,40 +407,323 @@ 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
|
||||||
|
|
||||||
|
#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
|
// Difference
|
||||||
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip )
|
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {
|
||||||
{
|
|
||||||
return polygon_clip( POLY_DIFF, subject, 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
|
// 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Exclusive or
|
// 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 );
|
return polygon_clip( POLY_XOR, subject, clip );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Union
|
// Union
|
||||||
TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip )
|
TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip ) {
|
||||||
{
|
|
||||||
return polygon_clip( POLY_UNION, subject, 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,
|
// canonify the polygon winding, outer contour must be anti-clockwise,
|
||||||
// all inner contours must be clockwise.
|
// all inner contours must be clockwise.
|
||||||
TGPolygon polygon_canonify( const TGPolygon& in_poly )
|
TGPolygon polygon_canonify( const TGPolygon& in_poly ) {
|
||||||
{
|
|
||||||
TGPolygon result;
|
TGPolygon result;
|
||||||
|
|
||||||
result.erase();
|
result.erase();
|
||||||
|
|
||||||
// Negative areas indicate counter clockwise winding. Postitive
|
// Negative areas indicate counter clockwise winding. Postitive
|
||||||
|
@ -473,19 +744,22 @@ TGPolygon polygon_canonify( const TGPolygon& in_poly )
|
||||||
// reverse contour
|
// reverse contour
|
||||||
point_list rcontour;
|
point_list rcontour;
|
||||||
rcontour.clear();
|
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] );
|
rcontour.push_back( contour[j] );
|
||||||
|
}
|
||||||
result.add_contour( rcontour, hole_flag );
|
result.add_contour( rcontour, hole_flag );
|
||||||
} else if ( !hole_flag && (area > 0) ) {
|
} else if ( !hole_flag && (area > 0) ) {
|
||||||
// reverse contour
|
// reverse contour
|
||||||
point_list rcontour;
|
point_list rcontour;
|
||||||
rcontour.clear();
|
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] );
|
rcontour.push_back( contour[j] );
|
||||||
|
}
|
||||||
result.add_contour( rcontour, hole_flag );
|
result.add_contour( rcontour, hole_flag );
|
||||||
} else
|
} else {
|
||||||
result.add_contour( contour, hole_flag );
|
result.add_contour( contour, hole_flag );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
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
|
// Traverse a polygon and split edges until they are less than max_len
|
||||||
// (specified in meters)
|
// (specified in meters)
|
||||||
TGPolygon tgPolygonSplitLongEdges( const TGPolygon &poly, double max_len )
|
TGPolygon tgPolygonSplitLongEdges( const TGPolygon &poly, double max_len ) {
|
||||||
{
|
|
||||||
TGPolygon result;
|
TGPolygon result;
|
||||||
Point3D p0, p1;
|
Point3D p0, p1;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
@ -510,7 +783,8 @@ TGPolygon tgPolygonSplitLongEdges( const TGPolygon &poly, double max_len )
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, " " << p0 << " - " << p1);
|
SG_LOG(SG_GENERAL, SG_DEBUG, " " << p0 << " - " << p1);
|
||||||
|
|
||||||
if ( fabs(p0.y()) < (90.0 - SG_EPSILON)
|
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;
|
double az1, az2, s;
|
||||||
geo_inverse_wgs_84( 0.0,
|
geo_inverse_wgs_84( 0.0,
|
||||||
p0.y(), p0.x(), p1.y(), p1.x(),
|
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
|
// 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();
|
TGPolygon result; result.erase();
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "strip_out_holes()");
|
SG_LOG(SG_GENERAL, SG_DEBUG, "strip_out_holes()");
|
||||||
|
@ -586,7 +859,7 @@ TGPolygon tgPolygonStripHoles( const TGPolygon &poly )
|
||||||
for ( int i = 0; i < poly.contours(); ++i ) {
|
for ( int i = 0; i < poly.contours(); ++i ) {
|
||||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "contour = " << i);
|
// SG_LOG(SG_GENERAL, SG_DEBUG, "contour = " << i);
|
||||||
point_list contour = poly.get_contour( i );
|
point_list contour = poly.get_contour( i );
|
||||||
if ( !poly.get_hole_flag(i) ) {
|
if ( ! poly.get_hole_flag(i) ) {
|
||||||
TGPolygon tmp;
|
TGPolygon tmp;
|
||||||
tmp.add_contour( contour, poly.get_hole_flag(i) );
|
tmp.add_contour( contour, poly.get_hole_flag(i) );
|
||||||
result = tgPolygonUnion( tmp, result );
|
result = tgPolygonUnion( tmp, result );
|
||||||
|
@ -596,20 +869,163 @@ TGPolygon tgPolygonStripHoles( const TGPolygon &poly )
|
||||||
return result;
|
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.
|
// Send a polygon to standard output.
|
||||||
ostream &
|
ostream &
|
||||||
operator<<(ostream &output, const TGPolygon &poly)
|
operator<< (ostream &output, const TGPolygon &poly)
|
||||||
{
|
{
|
||||||
int nContours = poly.contours();
|
int nContours = poly.contours();
|
||||||
|
|
||||||
output << nContours << endl;
|
output << nContours << endl;
|
||||||
for (int i = 0; i < nContours; i++) {
|
for (int i = 0; i < nContours; i++) {
|
||||||
int nPoints = poly.contour_size(i);
|
int nPoints = poly.contour_size(i);
|
||||||
output << nPoints << endl;
|
output << nPoints << endl;
|
||||||
output << poly.get_hole_flag(i) << 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;
|
output << poly.get_pt(i, j) << endl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return output; // MSVC
|
return output; // MSVC
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,26 @@
|
||||||
# error This library requires C++
|
# error This library requires C++
|
||||||
#endif
|
#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
|
/* which clipping lib to use? Looks like we should go with clipper
|
||||||
* It appears to be both faster and generates better accuracy
|
* It appears to be both faster and generates better accuracy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define CLIP_GPC
|
// forward declaration
|
||||||
#define CLIP_CLIPPER
|
class TGPolygon;
|
||||||
|
|
||||||
|
#define CLIP_GPC
|
||||||
|
// #define CLIP_CLIPPER
|
||||||
|
|
||||||
/* Set to 1 to allow keeping accum poly in native clipping lib format
|
/* 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
|
* 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
|
#if CLIP_NATIVE // optimization apparently causing errors
|
||||||
typedef gpc_polygon ClipPolyType;
|
typedef gpc_polygon ClipPolyType;
|
||||||
|
#else
|
||||||
|
typedef TGPolygon ClipPolyType;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CLIP_GPC */
|
#endif /* CLIP_GPC */
|
||||||
|
@ -60,19 +76,13 @@ using namespace ClipperLib;
|
||||||
|
|
||||||
#if CLIP_NATIVE // optimization apparently causing errors
|
#if CLIP_NATIVE // optimization apparently causing errors
|
||||||
typedef Polygons ClipPolyType;
|
typedef Polygons ClipPolyType;
|
||||||
|
#else
|
||||||
|
typedef TGPolygon ClipPolyType;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CLIP_CLIPPER */
|
#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
|
#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 std::vector < TGPolygon > poly_list;
|
||||||
typedef poly_list::iterator poly_list_iterator;
|
typedef poly_list::iterator poly_list_iterator;
|
||||||
typedef poly_list::const_iterator const_poly_list_iterator;
|
typedef poly_list::const_iterator const_poly_list_iterator;
|
||||||
|
|
Loading…
Add table
Reference in a new issue