- some clipperfixes for tgconstruct. bring in clipper 4.8.9
Hopefully, we can start another clc06 test with this fix - add lots of debug, in case more clipper issues uncovered added --debug-areas= allows turning on debug for an area can dump the accumulator when using it. - fixed the swirlies round 2 workaround on tile output, rather than stopping the load of polygons at arbitrary threshold. (hopefully, we'll have a fix for this in simgear soon) - modified ogr-decode (when using --texture-lines) to insert triangles instead of self-intersecting trapezoids when the turn angle between segments is too steep (hit this issue when experimenting with cgal-clipping) we were adding a lot of self intersecting polys on line data - needed to add gdal library to all executables that link against Polygon TODO - combne Geometry and Polygon libs - they are completely joined, now.
This commit is contained in:
parent
55bfcd80e7
commit
b44c6c00d0
18 changed files with 931 additions and 179 deletions
|
@ -20,6 +20,22 @@ target_link_libraries(tg-construct
|
|||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS tg-construct RUNTIME DESTINATION bin)
|
||||
|
||||
|
||||
|
||||
add_executable(cliptst
|
||||
cliptst.cxx)
|
||||
|
||||
target_link_libraries(cliptst
|
||||
Polygon Geometry
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
||||
install(TARGETS tg-construct RUNTIME DESTINATION bin)
|
||||
|
||||
INSTALL(FILES usgsmap.txt DESTINATION ${PKGDATADIR} )
|
||||
|
|
319
src/BuildTiles/Main/cliptst.cxx
Normal file
319
src/BuildTiles/Main/cliptst.cxx
Normal file
|
@ -0,0 +1,319 @@
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#include <Polygon/clipper.hpp>
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Geometry/poly_support.hxx>
|
||||
|
||||
//#include "windows.h"
|
||||
//#include <conio.h>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
using namespace std;
|
||||
using namespace ClipperLib;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline long64 Round(double val)
|
||||
{
|
||||
if ((val < 0)) return (long64)(val - 0.5); else return (long64)(val + 0.5);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int PrecisionFirstValue(const char * filename)
|
||||
{
|
||||
char line[80];
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (!f) return 0;
|
||||
if (fgets(line, 80, f) == 0) return 0; //skip poly count
|
||||
if (fgets(line, 80, f) == 0) return 0; //skip length first polygon
|
||||
if (fgets(line, 80, f) == 0) return 0; //get coords first vertex
|
||||
fclose(f);
|
||||
|
||||
int i = 0;
|
||||
while (line[i] >= ' ' && line[i] != '.') i++;
|
||||
if (line[i] != '.') return 0;
|
||||
i++;
|
||||
int j = i;
|
||||
while (line[j] >= '0' && line[j] <= '9') j++;
|
||||
return j - i;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool IsBlankLine(char* line)
|
||||
{
|
||||
while (*line)
|
||||
if (*line > ' ') return false;
|
||||
else line++;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool LoadFromFile(Polygons &ppg, char * filename, double scale)
|
||||
{
|
||||
ppg.clear();
|
||||
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (!f) return false;
|
||||
int polyCnt, vertCnt;
|
||||
char junk [80];
|
||||
double X, Y;
|
||||
|
||||
if (fscanf(f, "%d", &polyCnt) == 1 && polyCnt > 0)
|
||||
{
|
||||
ppg.resize(polyCnt);
|
||||
for (int i = 0; i < polyCnt; i++) {
|
||||
if (fscanf(f, "%d", &vertCnt) != 1 || vertCnt <= 0) break;
|
||||
ppg[i].resize(vertCnt);
|
||||
for (int j = 0; j < vertCnt; j++) {
|
||||
if (fscanf(f, "%lf%*[, ]%lf", &X, &Y) != 2) break;
|
||||
ppg[i][j].X = Round(X * scale);
|
||||
ppg[i][j].Y = Round(Y * scale);
|
||||
fgets(junk, 80, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool LoadFromFile2(Polygons &ppg, char * filename, double scale)
|
||||
{
|
||||
ppg.clear();
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (!f) return false;
|
||||
char line [80];
|
||||
double X, Y;
|
||||
Polygon pg;
|
||||
while (fgets(line, sizeof line, f))
|
||||
{
|
||||
if (IsBlankLine(line))
|
||||
{
|
||||
if (pg.size() > 0)
|
||||
{
|
||||
ppg.push_back(pg);
|
||||
pg.clear();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (sscanf(line, "%lf%*[, ]%lf", &X, &Y) != 2) break;
|
||||
pg.push_back(IntPoint(Round(X * scale), Round(Y * scale)));
|
||||
}
|
||||
if (pg.size() > 0) ppg.push_back(pg);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SaveToFile(char *filename, Polygons &pp, int precision)
|
||||
{
|
||||
double scale = std::pow(double(10), precision);
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (!f) return;
|
||||
fprintf(f, "%d\n", pp.size());
|
||||
for (unsigned i = 0; i < pp.size(); ++i)
|
||||
{
|
||||
fprintf(f, "%d\n", pp[i].size());
|
||||
if (precision != 0) {
|
||||
for (unsigned j = 0; j < pp[i].size(); ++j)
|
||||
fprintf(f, "%.*lf, %.*lf,\n",
|
||||
precision, (double)pp[i][j].X /scale,
|
||||
precision, (double)pp[i][j].Y /scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned j = 0; j < pp[i].size(); ++j)
|
||||
fprintf(f, "%lld, %lld,\n", pp[i][j].X, pp[i][j].Y );
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void SaveToFile(char *filename, ExPolygons &pp, int precision)
|
||||
{
|
||||
double scale = std::pow(double(10), precision);
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (!f) return;
|
||||
int cnt = 0;
|
||||
for (unsigned i = 0; i < pp.size(); ++i)
|
||||
cnt += pp[i].holes.size() +1;
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fprintf(f, "%d\n", cnt);
|
||||
for (unsigned i = 0; i < pp.size(); ++i)
|
||||
{
|
||||
fprintf(f, "%d\n", pp[i].outer.size());
|
||||
if (precision != 0) {
|
||||
for (unsigned j = 0; j < pp[i].outer.size(); ++j)
|
||||
fprintf(f, "%.*lf, %.*lf,\n",
|
||||
precision, (double)pp[i].outer[j].X /scale,
|
||||
precision, (double)pp[i].outer[j].Y /scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned j = 0; j < pp[i].outer.size(); ++j)
|
||||
fprintf(f, "%lld, %lld,\n", pp[i].outer[j].X, pp[i].outer[j].Y );
|
||||
}
|
||||
for (unsigned k = 0; k < pp[i].holes.size(); ++k)
|
||||
{
|
||||
fprintf(f, "%d\n", pp[i].holes[k].size());
|
||||
if (precision != 0) {
|
||||
for (unsigned j = 0; j < pp[i].holes[k].size(); ++j)
|
||||
fprintf(f, "%.*lf, %.*lf,\n",
|
||||
precision, (double)pp[i].holes[k][j].X /scale,
|
||||
precision, (double)pp[i].holes[k][j].Y /scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned j = 0; j < pp[i].holes[k].size(); ++j)
|
||||
fprintf(f, "%lld, %lld,\n", pp[i].holes[k][j].X, pp[i].holes[k][j].Y );
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void SaveToFileOstream(char *filename, Polygons &pp)
|
||||
{
|
||||
std::ofstream file;
|
||||
|
||||
file.open (filename);
|
||||
file << pp;
|
||||
file.close();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
#else
|
||||
int main(int argc, char* argv[])
|
||||
#endif
|
||||
{
|
||||
if (argc < 4)
|
||||
{
|
||||
cout << "\nUSAGE:\n"
|
||||
<< "clipper subject_file clip_file CLIPTYPE [SUBJ_FILL CLIP_FILL] [SVG]\n\n"
|
||||
<< " CLIPTYPE = i[ntersection] or u[nion] or d[ifference] or x[or], and\n"
|
||||
<< " SUBJ_FILL & CLIP_FILL = evenodd or nonzero (default = nonzero)\n"
|
||||
<< " SVG = Create SVG file\n"
|
||||
<< " where parameters in [] are optional\n\n";
|
||||
|
||||
//format 1
|
||||
//cout << "\nFORMAT OF INPUT AND OUTPUT FILES:\n"
|
||||
// << "Polygon Count {must be on the first line}\n"
|
||||
// << "Vertex Count {of first polygon}\n"
|
||||
// << "X[,] Y[,] {first vertex}\n"
|
||||
// << "X[,] Y[,] {next vertex}\n"
|
||||
// << "...\n"
|
||||
// << "Vertex Count {of second polygon, if there is one}\n"
|
||||
// << "X[,] Y[,] {first vertex of second polygon}\n"
|
||||
// << "...\n\n";
|
||||
|
||||
//format 2
|
||||
cout << "\nFORMAT OF INPUT AND OUTPUT FILES:\n"
|
||||
<< "Each polygon is separated by a blank line \n"
|
||||
<< "X[,] Y[,] {first vertex}\n"
|
||||
<< "X[,] Y[,] {next vertex}\n"
|
||||
<< "...\n"
|
||||
<< "\n"
|
||||
<< "X[,] Y[,] {first vertex of second polygon}\n"
|
||||
<< "...\n\n";
|
||||
|
||||
cout << "\nEXAMPLE:\n"
|
||||
<< "clipper subj.txt clip.txt u evenodd evenodd SVG\n\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int precision = PrecisionFirstValue(argv[1]);
|
||||
double scale = std::pow(double(10), precision);
|
||||
|
||||
bool show_svg =
|
||||
((argc > 4 && strcasecmp(argv[4], "SVG") == 0) ||
|
||||
(argc > 5 && strcasecmp(argv[5], "SVG") == 0) ||
|
||||
(argc > 6 && strcasecmp(argv[6], "SVG") == 0));
|
||||
|
||||
Polygons subject, clip;
|
||||
|
||||
if (!LoadFromFile2(subject, argv[1], scale))
|
||||
{
|
||||
cerr << "\nCan't open the file " << argv[1]
|
||||
<< " or the file format is invalid.\n";
|
||||
return 1;
|
||||
}
|
||||
if (!LoadFromFile2(clip, argv[2], scale))
|
||||
{
|
||||
cerr << "\nCan't open the file " << argv[2]
|
||||
<< " or the file format is invalid.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (show_svg) {
|
||||
tgShapefileInit();
|
||||
clipper_to_shapefile( subject, "./clptst_subject" );
|
||||
clipper_to_shapefile( clip, "./clptst_clip" );
|
||||
}
|
||||
|
||||
ClipType clipType;
|
||||
switch (toupper(argv[3][0])) {
|
||||
case 'X': clipType = ctXor; break;
|
||||
case 'U': clipType = ctUnion; break;
|
||||
case 'D': clipType = ctDifference; break;
|
||||
default: clipType = ctIntersection;
|
||||
}
|
||||
|
||||
PolyFillType subj_pft = pftNonZero, clip_pft = pftNonZero;
|
||||
if (argc > 4&& strcasecmp(argv[4], "EVENODD") == 0)
|
||||
subj_pft = pftEvenOdd;
|
||||
if (argc > 5 && strcasecmp(argv[5], "EVENODD") == 0)
|
||||
clip_pft = pftEvenOdd;
|
||||
|
||||
cout << "\nclipping ... ";
|
||||
|
||||
Clipper c;
|
||||
c.AddPolygons(subject, ptSubject);
|
||||
c.AddPolygons(clip, ptClip);
|
||||
Polygons solution;
|
||||
|
||||
// double elapsed = 0;
|
||||
// _LARGE_INTEGER qpf, qpc1, qpc2;
|
||||
// bool HPMEnabled = QueryPerformanceFrequency(&qpf);
|
||||
// if (HPMEnabled) QueryPerformanceCounter(&qpc1);
|
||||
|
||||
bool succeeded = c.Execute(clipType, solution, subj_pft, clip_pft);
|
||||
|
||||
// if (HPMEnabled) {
|
||||
// QueryPerformanceCounter(&qpc2);
|
||||
// elapsed = double(qpc2.QuadPart - qpc1.QuadPart) / qpf.QuadPart;
|
||||
// cout << "\nEllapsed: " << elapsed;
|
||||
// }
|
||||
|
||||
if (succeeded) {
|
||||
SaveToFile("solution.txt", solution, precision);
|
||||
SaveToFileOstream("solution_ostream", solution );
|
||||
cout << "succeeded.\nSolution saved to - solution.txt.\n\n";
|
||||
cout << "\n";
|
||||
|
||||
if( show_svg ) {
|
||||
cout << "Generating shapefile\n";
|
||||
clipper_to_shapefile( solution, "./clptst_solution" );
|
||||
}
|
||||
} else
|
||||
cout << "failed.\n\n";
|
||||
return 0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
|
@ -91,15 +91,42 @@ TGConstruct::~TGConstruct() {
|
|||
nodes.clear();
|
||||
}
|
||||
|
||||
void TGConstruct::set_debug( std::string path, std::vector<string> defs )
|
||||
void TGConstruct::set_debug( std::string path, std::vector<string> area_defs, std::vector<string> shape_defs )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Set debug Path " << path);
|
||||
|
||||
debug_path = path;
|
||||
|
||||
/* Find any ids for our tile */
|
||||
for (unsigned int i=0; i< defs.size(); i++) {
|
||||
string dsd = defs[i];
|
||||
for (unsigned int i=0; i< area_defs.size(); i++) {
|
||||
string dsd = area_defs[i];
|
||||
size_t d_pos = dsd.find(":");
|
||||
string tile = dsd.substr(0, d_pos);
|
||||
|
||||
if( tile == bucket.gen_index_str() ) {
|
||||
dsd.erase(0, d_pos+1);
|
||||
|
||||
if ( dsd == "all" ) {
|
||||
debug_all = true;
|
||||
} else {
|
||||
std::stringstream ss(dsd);
|
||||
int i;
|
||||
|
||||
while (ss >> i)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Adding debug file " << i);
|
||||
|
||||
debug_areas.push_back(i);
|
||||
|
||||
if (ss.peek() == ',')
|
||||
ss.ignore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i=0; i< shape_defs.size(); i++) {
|
||||
string dsd = shape_defs[i];
|
||||
size_t d_pos = dsd.find(":");
|
||||
string tile = dsd.substr(0, d_pos);
|
||||
|
||||
|
@ -145,6 +172,25 @@ bool TGConstruct::IsDebugShape( unsigned int id )
|
|||
return is_debug;
|
||||
}
|
||||
|
||||
bool TGConstruct::IsDebugArea( unsigned int area )
|
||||
{
|
||||
bool is_debug = false;
|
||||
|
||||
/* Check global flag */
|
||||
if ( debug_all ) {
|
||||
is_debug = true;
|
||||
} else {
|
||||
for (unsigned int i=0; i<debug_areas.size(); i++) {
|
||||
if ( debug_areas[i] == area ) {
|
||||
is_debug = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is_debug;
|
||||
}
|
||||
|
||||
void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape )
|
||||
{
|
||||
char name[64];
|
||||
|
@ -153,7 +199,7 @@ void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape
|
|||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, "test" );
|
||||
tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, name );
|
||||
|
||||
// close after each write
|
||||
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||
|
@ -293,22 +339,7 @@ bool TGConstruct::load_poly(const string& path) {
|
|||
poly_type = get_area_type( poly_name );
|
||||
|
||||
int area = (int)poly_type;
|
||||
string material;
|
||||
|
||||
// only allow 1000 shapes per material
|
||||
int extension = polys_in.area_size( area ) / 1000;
|
||||
|
||||
if (extension)
|
||||
{
|
||||
char buff[32];
|
||||
sprintf( buff, "%s_%d", get_area_name( area ).c_str(), extension );
|
||||
material = buff;
|
||||
}
|
||||
else
|
||||
{
|
||||
material = get_area_name( area );
|
||||
}
|
||||
|
||||
string material = get_area_name( area );
|
||||
|
||||
// Generate a new Shape for the poly
|
||||
TGShape shape;
|
||||
|
@ -1275,6 +1306,8 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
int i, j;
|
||||
Point3D p;
|
||||
point2d min, max;
|
||||
bool debug_area, debug_shape;
|
||||
static int accum_idx = 0;
|
||||
|
||||
#if !USE_ACCUMULATOR
|
||||
TGPolygon accum;
|
||||
|
@ -1342,7 +1375,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
}
|
||||
|
||||
// Dump the masks
|
||||
if ( debug_all || debug_shapes.size() ) {
|
||||
if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
|
||||
WriteDebugPoly( "land_mask", "", land_mask );
|
||||
WriteDebugPoly( "water_mask", "", water_mask );
|
||||
WriteDebugPoly( "island_mask", "", island_mask );
|
||||
|
@ -1350,10 +1383,13 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
|
||||
// process polygons in priority order
|
||||
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
||||
debug_area = IsDebugArea( i );
|
||||
|
||||
for( j = 0; j < (int)polys_in.area_size(i); ++j ) {
|
||||
TGPolygon current = polys_in.get_mask(i, j);
|
||||
debug_shape = IsDebugShape( polys_in.get_shape( i, j ).id );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Clipping " << get_area_name( (AreaType)i ) << ":" << j+1 << " of " << polys_in.area_size(i) );
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Clipping " << get_area_name( (AreaType)i ) << ":" << j+1 << " of " << polys_in.area_size(i) << " accum_idx: " << accum_idx );
|
||||
|
||||
tmp = current;
|
||||
|
||||
|
@ -1368,18 +1404,39 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
tmp = tgPolygonDiffClipper( tmp, island_mask );
|
||||
}
|
||||
|
||||
if ( IsDebugShape( polys_in.get_shape( i, j ).id ) ) {
|
||||
if ( debug_area || debug_shape ) {
|
||||
char layer[32];
|
||||
char name[32];
|
||||
sprintf(layer, "pre_clip_%d", polys_in.get_shape( i, j ).id );
|
||||
sprintf(name, "shape %d,%d", i,j);
|
||||
WriteDebugPoly( "pre-clip", name, tmp );
|
||||
WriteDebugPoly( layer, name, tmp );
|
||||
|
||||
sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_shape( i, j ).id );
|
||||
sprintf(name, "shape_accum %d,%d", i,j);
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
tgPolygonDumpAccumulator( ds_name, layer, name );
|
||||
#else
|
||||
WriteDebugPoly( layer, name, accum );
|
||||
#endif
|
||||
}
|
||||
|
||||
// simplify polygon before clipping
|
||||
tmp = tgPolygonSimplify( tmp );
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
clipped = tgPolygonDiffClipperWithAccumulator( tmp );
|
||||
#else
|
||||
clipped = tgPolygonDiffClipper( tmp, accum );
|
||||
clipped = tgPolygonDiff( tmp, accum );
|
||||
#endif
|
||||
|
||||
if ( debug_area || debug_shape ) {
|
||||
char layer[32];
|
||||
char name[32];
|
||||
sprintf(layer, "post_clip_%d", polys_in.get_shape( i, j ).id );
|
||||
sprintf(name, "shape %d,%d", i,j);
|
||||
WriteDebugPoly( layer, name, clipped );
|
||||
}
|
||||
|
||||
// only add to output list if the clip left us with a polygon
|
||||
if ( clipped.contours() > 0 ) {
|
||||
|
@ -1405,22 +1462,39 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
// shape.sps.push_back( sp );
|
||||
polys_clipped.add_shape( i, shape );
|
||||
|
||||
if ( IsDebugShape( shape.id ) ) {
|
||||
if ( debug_area || debug_shape ) {
|
||||
WriteDebugShape( "clipped", shape );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
tgPolygonAddToClipperAccumulator( tmp );
|
||||
if ( debug_shape ) {
|
||||
tgPolygonAddToClipperAccumulator( tmp, true );
|
||||
} else {
|
||||
tgPolygonAddToClipperAccumulator( tmp, false );
|
||||
}
|
||||
#else
|
||||
accum = tgPolygonUnionClipper( tmp, accum );
|
||||
#endif
|
||||
|
||||
if ( debug_area || debug_shape ) {
|
||||
char layer[32];
|
||||
char name[32];
|
||||
sprintf(layer, "post_clip_accum_%d_%d", accum_idx, polys_in.get_shape( i, j ).id );
|
||||
sprintf(name, "shape_accum %d,%d", i,j);
|
||||
#if USE_ACCUMULATOR
|
||||
tgPolygonDumpAccumulator( ds_name, layer, name );
|
||||
#else
|
||||
WriteDebugPoly( layer, name, accum );
|
||||
#endif
|
||||
}
|
||||
|
||||
accum_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( debug_all || debug_shapes.size() ) {
|
||||
if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
|
||||
// Dump the sliver list
|
||||
WriteDebugPolys( "poly_slivers", slivers );
|
||||
}
|
||||
|
@ -1455,7 +1529,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
// neighboring polygons
|
||||
if ( slivers.size() > 0 ) {
|
||||
|
||||
if ( debug_all || debug_shapes.size() ) {
|
||||
if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
|
||||
// Dump the sliver list
|
||||
WriteDebugPolys( "remains_slivers", slivers );
|
||||
}
|
||||
|
@ -1764,7 +1838,9 @@ void TGConstruct::TesselatePolys( void )
|
|||
unsigned int id = polys_clipped.get_shape( area, shape ).id;
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
WriteDebugShape( "preteselate", polys_clipped.get_shape(area, shape) );
|
||||
char layer[32];
|
||||
sprintf( layer, " pretess-%d", id );
|
||||
WriteDebugShape( layer, polys_clipped.get_shape(area, shape) );
|
||||
}
|
||||
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
|
@ -1821,8 +1897,12 @@ void TGConstruct::WriteBtgFile( void )
|
|||
int_list tri_tc, strip_tc;
|
||||
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
unsigned int area_tris;
|
||||
|
||||
// only tesselate non holes
|
||||
if ( !is_hole_area( area ) ) {
|
||||
area_tris = 0;
|
||||
|
||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" <<
|
||||
|
@ -1830,7 +1910,7 @@ void TGConstruct::WriteBtgFile( void )
|
|||
|
||||
TGPolyNodes tri_nodes = polys_clipped.get_tri_idxs(area, shape, segment);
|
||||
TGPolygon tri_txs = polys_clipped.get_texcoords(area, shape, segment);
|
||||
string material = polys_clipped.get_material(area, shape, segment);
|
||||
string material;
|
||||
|
||||
for (int k = 0; k < tri_nodes.contours(); ++k) {
|
||||
tri_v.clear();
|
||||
|
@ -1851,7 +1931,28 @@ void TGConstruct::WriteBtgFile( void )
|
|||
tris_v.push_back( tri_v );
|
||||
tris_n.push_back( tri_n );
|
||||
tris_tc.push_back( tri_tc );
|
||||
tri_materials.push_back( material );
|
||||
|
||||
switch ( area_tris / 32768 ) {
|
||||
case 0:
|
||||
material = polys_clipped.get_material(area, shape, segment);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
material = polys_clipped.get_material(area, shape, segment) + "_1";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
material = polys_clipped.get_material(area, shape, segment) + "_2";
|
||||
break;
|
||||
|
||||
case 3:
|
||||
material = polys_clipped.get_material(area, shape, segment) + "_3";
|
||||
break;
|
||||
}
|
||||
|
||||
tri_materials.push_back( material );
|
||||
|
||||
area_tris++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1927,7 +2028,7 @@ void TGConstruct::WriteBtgFile( void )
|
|||
{
|
||||
throw sg_exception("error writing file. :-(");
|
||||
}
|
||||
if (debug_all || debug_shapes.size())
|
||||
if (debug_all || debug_shapes.size() || debug_areas.size() )
|
||||
{
|
||||
result = obj.write_ascii( base, txtname, bucket );
|
||||
if ( !result )
|
||||
|
@ -2026,7 +2127,7 @@ void TGConstruct::ConstructBucketStage1() {
|
|||
SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
|
||||
|
||||
/* If we have some debug IDs, create a datasource */
|
||||
if ( debug_shapes.size() || debug_all ) {
|
||||
if ( debug_shapes.size() || debug_all || debug_areas.size() ) {
|
||||
sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() );
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Debug_string: " << ds_name );
|
||||
} else {
|
||||
|
|
|
@ -271,6 +271,7 @@ private:
|
|||
bool debug_all;
|
||||
|
||||
// list of shapes to dump during debug
|
||||
std::vector<unsigned int> debug_areas;
|
||||
std::vector<unsigned int> debug_shapes;
|
||||
|
||||
// OGR encode variables
|
||||
|
@ -346,6 +347,8 @@ private:
|
|||
|
||||
// debug
|
||||
bool IsDebugShape( unsigned int id );
|
||||
bool IsDebugArea( unsigned int area );
|
||||
|
||||
void WriteDebugShape( const char* layer_name, const TGShape& shape );
|
||||
void WriteDebugPoly( const char* layer_name, const char* name, const TGPolygon& poly );
|
||||
void WriteDebugPolys( const char* layer_name, const poly_list& polys );
|
||||
|
@ -415,7 +418,7 @@ public:
|
|||
inline point_list get_point_normals() const { return nodes.get_normals(); }
|
||||
|
||||
// Debug
|
||||
void set_debug( std::string path, std::vector<std::string> defs );
|
||||
void set_debug( std::string path, std::vector<std::string> area_defs, std::vector<std::string> shape_defs );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -168,7 +168,8 @@ int main(int argc, char **argv) {
|
|||
long tile_id = -1;
|
||||
|
||||
string debug_dir = ".";
|
||||
vector<string> debug_defs;
|
||||
vector<string> debug_shape_defs;
|
||||
vector<string> debug_area_defs;
|
||||
|
||||
// flag indicating whether UK grid should be used for in-UK
|
||||
// texture coordinate generation
|
||||
|
@ -230,8 +231,10 @@ int main(int argc, char **argv) {
|
|||
ignoreLandmass = true;
|
||||
} else if (arg.find("--debug-dir=") == 0) {
|
||||
debug_dir = arg.substr(12);
|
||||
} else if (arg.find("--debug-areas=") == 0) {
|
||||
debug_area_defs.push_back( arg.substr(14) );
|
||||
} else if (arg.find("--debug-shapes=") == 0) {
|
||||
debug_defs.push_back( arg.substr(15) );
|
||||
debug_shape_defs.push_back( arg.substr(15) );
|
||||
} else if (arg.find("--") == 0) {
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
|
@ -292,7 +295,7 @@ int main(int argc, char **argv) {
|
|||
c->set_nudge( nudge );
|
||||
c->set_bucket( b );
|
||||
|
||||
c->set_debug( debug_dir, debug_defs );
|
||||
c->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||
|
||||
c->ConstructBucketStage1();
|
||||
delete c;
|
||||
|
@ -321,7 +324,7 @@ int main(int argc, char **argv) {
|
|||
c->set_nudge( nudge );
|
||||
c->set_bucket( b_min );
|
||||
|
||||
c->set_debug( debug_dir, debug_defs );
|
||||
c->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||
|
||||
c->ConstructBucketStage1();
|
||||
delete c;
|
||||
|
@ -355,7 +358,7 @@ int main(int argc, char **argv) {
|
|||
c->set_nudge( nudge );
|
||||
c->set_bucket( b_cur );
|
||||
|
||||
c->set_debug( debug_dir, debug_defs );
|
||||
c->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||
|
||||
c->ConstructBucketStage1();
|
||||
delete c;
|
||||
|
@ -384,7 +387,7 @@ int main(int argc, char **argv) {
|
|||
c->set_nudge( nudge );
|
||||
c->set_bucket( b );
|
||||
|
||||
c->set_debug( debug_dir, debug_defs );
|
||||
c->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||
|
||||
c->ConstructBucketStage1();
|
||||
delete c;
|
||||
|
|
|
@ -16,6 +16,16 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
// use cgal for intersection, old implementation returns true, even when line SEGMENTS don't intersect
|
||||
// CGAL intersection can do that with lines, but we want to use segments (end at the first and last point)
|
||||
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/intersections.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef CGAL::Segment_2<Kernel> Segment_2;
|
||||
|
||||
#define MP_STRETCH (0.000001)
|
||||
|
||||
using std::string;
|
||||
|
@ -57,6 +67,34 @@ getIntersection (const Point3D &p0, const Point3D &p1,
|
|||
}
|
||||
}
|
||||
|
||||
// use CGAL
|
||||
|
||||
bool getIntersection_cgal(const Point3D &p0, const Point3D &p1,
|
||||
const Point3D &p2, const Point3D &p3,
|
||||
Point3D &intersection)
|
||||
{
|
||||
Point_2 a1( p0.x(), p0.y() );
|
||||
Point_2 b1( p1.x(), p1.y() );
|
||||
Point_2 a2( p2.x(), p2.y() );
|
||||
Point_2 b2( p3.x(), p3.y() );
|
||||
|
||||
Segment_2 seg1( a1, b1 );
|
||||
Segment_2 seg2( a2, b2 );
|
||||
|
||||
CGAL::Object result = CGAL::intersection(seg1, seg2);
|
||||
if (const CGAL::Point_2<Kernel> *ipoint = CGAL::object_cast<CGAL::Point_2<Kernel> >(&result)) {
|
||||
// handle the point intersection case with *ipoint.
|
||||
return true;
|
||||
} else {
|
||||
if (const CGAL::Segment_2<Kernel> *iseg = CGAL::object_cast<CGAL::Segment_2<Kernel> >(&result)) {
|
||||
// handle the segment intersection case with *iseg.
|
||||
return false;
|
||||
} else {
|
||||
// handle the no intersection case.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a polygon out of a point.
|
||||
|
@ -503,6 +541,7 @@ makePolygons (const Line &line, double width, poly_list& polys)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
makePolygonsTP (const Line &line, double width, poly_list& polys, texparams_list &tps)
|
||||
{
|
||||
|
@ -600,6 +639,147 @@ makePolygonsTP (const Line &line, double width, poly_list& polys, texparams_list
|
|||
prev_inner = cur_inner;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
makePolygonsTP (const Line &line, double width, poly_list& polys, texparams_list &tps)
|
||||
{
|
||||
int nPoints = line.getPointCount();
|
||||
int i;
|
||||
int turn_dir;
|
||||
|
||||
Point3D cur_inner;
|
||||
Point3D cur_outer;
|
||||
Point3D prev_inner = Point3D(0.0f, 0.0f, 0.0f);
|
||||
Point3D prev_outer = Point3D(0.0f, 0.0f, 0.0f);
|
||||
Point3D calc_inner;
|
||||
Point3D calc_outer;
|
||||
|
||||
double last_end_v = 0.0f;
|
||||
double heading = 0.0f;
|
||||
double az2 = 0.0f;
|
||||
double dist = 0.0f;
|
||||
|
||||
TGPolygon poly;
|
||||
TGPolygon accum;
|
||||
TGTexParams tp;
|
||||
|
||||
// generate poly and texparam lists for each line segment
|
||||
for (i=0; i<nPoints; i++)
|
||||
{
|
||||
last_end_v = 0.0f;
|
||||
turn_dir = 0;
|
||||
|
||||
sglog().setLogLevels( SG_ALL, SG_INFO );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "makePolygonsTP: calculating offsets for segment " << i);
|
||||
|
||||
// for each point on the PointsList, generate a quad from
|
||||
// start to next, offset by 1/2 width from the edge
|
||||
if (i == 0)
|
||||
{
|
||||
// first point on the list - offset heading is 90deg
|
||||
cur_outer = OffsetPointFirst( line.getPoint(i), line.getPoint(i+1), -width/2.0f );
|
||||
cur_inner = OffsetPointFirst( line.getPoint(i), line.getPoint(i+1), width/2.0f );
|
||||
}
|
||||
else if (i == nPoints-1)
|
||||
{
|
||||
// last point on the list - offset heading is 90deg
|
||||
cur_outer = OffsetPointLast( line.getPoint(i-1), line.getPoint(i), -width/2.0f );
|
||||
cur_inner = OffsetPointLast( line.getPoint(i-1), line.getPoint(i), width/2.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// middle section
|
||||
cur_outer = OffsetPointMiddle( line.getPoint(i-1), line.getPoint(i), line.getPoint(i+1), -width/2.0f, turn_dir );
|
||||
cur_inner = OffsetPointMiddle( line.getPoint(i-1), line.getPoint(i), line.getPoint(i+1), width/2.0f, turn_dir );
|
||||
}
|
||||
|
||||
if ( (prev_inner.x() != 0.0f) && (prev_inner.y() != 0.0f) )
|
||||
{
|
||||
// draw the poly in simplified arrow format
|
||||
TGPolygon ref_trap;
|
||||
|
||||
ref_trap.add_node( 0, prev_inner );
|
||||
ref_trap.add_node( 0, prev_outer );
|
||||
ref_trap.add_node( 0, cur_outer );
|
||||
ref_trap.add_node( 0, cur_inner );
|
||||
}
|
||||
|
||||
if ( (prev_inner.x() != 0.0f) && (prev_inner.y() != 0.0f) )
|
||||
{
|
||||
Point3D prev_mp = midpoint( prev_outer, prev_inner );
|
||||
Point3D cur_mp = midpoint( cur_outer, cur_inner );
|
||||
Point3D intersect;
|
||||
|
||||
geo_inverse_wgs_84( prev_mp.y(), prev_mp.x(), cur_mp.y(), cur_mp.x(), &heading, &az2, &dist);
|
||||
|
||||
poly.erase();
|
||||
|
||||
poly.add_node( 0, prev_inner );
|
||||
poly.add_node( 0, prev_outer );
|
||||
|
||||
// we need to extend one of the points so we're sure we don't create adjacent edges
|
||||
if (turn_dir == 0)
|
||||
{
|
||||
// turned right - offset outer
|
||||
geo_inverse_wgs_84( prev_outer.y(), prev_outer.x(), cur_outer.y(), cur_outer.x(), &heading, &az2, &dist);
|
||||
|
||||
// CHECK for self inersecting poly - angle too steep for this width
|
||||
if ( getIntersection_cgal( prev_inner, prev_outer, cur_inner, cur_outer, intersect ) )
|
||||
{
|
||||
// yes - make a triangle with inner edge = 0
|
||||
poly.add_node( 0, cur_outer );
|
||||
cur_inner = prev_inner;
|
||||
}
|
||||
else
|
||||
{
|
||||
poly.add_node( 0, cur_outer );
|
||||
poly.add_node( 0, cur_inner );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// turned left - offset inner
|
||||
geo_inverse_wgs_84( prev_inner.y(), prev_inner.x(), cur_inner.y(), cur_inner.x(), &heading, &az2, &dist);
|
||||
|
||||
if ( getIntersection_cgal( prev_inner, prev_outer, cur_inner, cur_outer, intersect ) )
|
||||
{
|
||||
// yes - make a triangle with outer edge = 0
|
||||
poly.add_node( 0, cur_inner );
|
||||
cur_outer = prev_outer;
|
||||
}
|
||||
else
|
||||
{
|
||||
poly.add_node( 0, cur_outer );
|
||||
poly.add_node( 0, cur_inner );
|
||||
}
|
||||
}
|
||||
|
||||
// draw the poly in simplified arrow format
|
||||
TGPolygon ref_tri;
|
||||
|
||||
ref_tri.add_node( 0, prev_inner );
|
||||
ref_tri.add_node( 0, prev_outer );
|
||||
|
||||
Point3D mp = midpoint( cur_inner, cur_outer );
|
||||
ref_tri.add_node( 0, mp );
|
||||
|
||||
polys.push_back(poly);
|
||||
|
||||
tp = TGTexParams( prev_inner, width, 20.0f, heading );
|
||||
tp.set_minv(last_end_v);
|
||||
tps.push_back(tp);
|
||||
|
||||
last_end_v = 1.0f - (fmod( (double)(dist - last_end_v), (double)1.0f ));
|
||||
}
|
||||
|
||||
prev_outer = cur_outer;
|
||||
prev_inner = cur_inner;
|
||||
}
|
||||
|
||||
sglog().setLogLevels( SG_ALL, SG_INFO );
|
||||
}
|
||||
|
||||
|
||||
Rectangle
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* *
|
||||
* Author : Angus Johnson *
|
||||
* Version : 4.8.3 *
|
||||
* Date : 27 May 2012 *
|
||||
* Version : 4.8.9 *
|
||||
* Date : 25 September 2012 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2012 *
|
||||
* *
|
||||
|
@ -49,8 +49,8 @@
|
|||
|
||||
namespace ClipperLib {
|
||||
|
||||
static long64 const loRange = 1518500249; //sqrt(2^63 -1)/2
|
||||
static long64 const hiRange = 6521908912666391106LL; //sqrt(2^127 -1)/2
|
||||
static long64 const loRange = 0x3FFFFFFF;
|
||||
static long64 const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
||||
static double const pi = 3.141592653589793238;
|
||||
enum Direction { dRightToLeft, dLeftToRight };
|
||||
|
||||
|
@ -61,7 +61,7 @@ enum Direction { dRightToLeft, dLeftToRight };
|
|||
|
||||
inline long64 Abs(long64 val)
|
||||
{
|
||||
if (val < 0) return -val; else return val;
|
||||
return val < 0 ? -val : val;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -114,6 +114,12 @@ class Int128
|
|||
return lo < val.lo;
|
||||
}
|
||||
|
||||
bool operator >= (const Int128 &val) const
|
||||
{ return !(*this < val);}
|
||||
|
||||
bool operator <= (const Int128 &val) const
|
||||
{ return !(*this > val);}
|
||||
|
||||
Int128& operator += (const Int128 &rhs)
|
||||
{
|
||||
hi += rhs.hi;
|
||||
|
@ -349,10 +355,10 @@ bool Orientation(const Polygon &poly)
|
|||
throw "Coordinate exceeds range bounds.";
|
||||
Int128 cross = Int128(vec1.X) * Int128(vec2.Y) -
|
||||
Int128(vec2.X) * Int128(vec1.Y);
|
||||
return cross > 0;
|
||||
return cross >= 0;
|
||||
}
|
||||
else
|
||||
return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0;
|
||||
return (vec1.X * vec2.Y - vec2.X * vec1.Y) >= 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -394,9 +400,9 @@ bool Orientation(OutRec *outRec, bool UseFullInt64Range)
|
|||
ip2.Y = opNext->pt.Y - op->pt.Y;
|
||||
|
||||
if (UseFullInt64Range)
|
||||
return Int128(ip1.X) * Int128(ip2.Y) - Int128(ip2.X) * Int128(ip1.Y) > 0;
|
||||
return Int128(ip1.X) * Int128(ip2.Y) - Int128(ip2.X) * Int128(ip1.Y) >= 0;
|
||||
else
|
||||
return (ip1.X * ip2.Y - ip2.X * ip1.Y) > 0;
|
||||
return (ip1.X * ip2.Y - ip2.X * ip1.Y) >= 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -619,11 +625,22 @@ bool IntersectPoint(TEdge &edge1, TEdge &edge2,
|
|||
ip.X = Round(edge1.dx * b2 + b1);
|
||||
}
|
||||
|
||||
return
|
||||
//can be *so close* to the top of one edge that the rounded Y equals one ytop ...
|
||||
(ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) ||
|
||||
(ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) ||
|
||||
(ip.Y > edge1.ytop && ip.Y > edge2.ytop);
|
||||
if (ip.Y < edge1.ytop || ip.Y < edge2.ytop)
|
||||
{
|
||||
if (edge1.ytop > edge2.ytop)
|
||||
{
|
||||
ip.X = edge1.xtop;
|
||||
ip.Y = edge1.ytop;
|
||||
return TopX(edge2, edge1.ytop) < edge1.xtop;
|
||||
} else
|
||||
{
|
||||
ip.X = edge2.xtop;
|
||||
ip.Y = edge2.ytop;
|
||||
return TopX(edge1, edge2.ytop) > edge2.xtop;
|
||||
}
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -1221,7 +1238,7 @@ bool PolySort(OutRec *or1, OutRec *or2)
|
|||
{
|
||||
if (or1->pts != or2->pts)
|
||||
{
|
||||
if (or1->pts) return true; else return false;
|
||||
return or1->pts ? true : false;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
@ -1235,8 +1252,7 @@ bool PolySort(OutRec *or1, OutRec *or2)
|
|||
int result = i1 - i2;
|
||||
if (result == 0 && (or1->isHole != or2->isHole))
|
||||
{
|
||||
if (or1->isHole) return false;
|
||||
else return true;
|
||||
return or1->isHole ? false : true;
|
||||
}
|
||||
else return result < 0;
|
||||
}
|
||||
|
@ -1309,10 +1325,7 @@ bool Clipper::ExecuteInternal(bool fixHoleLinkages)
|
|||
|
||||
if (outRec->bottomPt == outRec->bottomFlag &&
|
||||
(Orientation(outRec, m_UseFullRange) != (Area(*outRec, m_UseFullRange) > 0)))
|
||||
{
|
||||
DisposeBottomPt(*outRec);
|
||||
FixupOutPolygon(*outRec);
|
||||
};
|
||||
DisposeBottomPt(*outRec);
|
||||
|
||||
if (outRec->isHole ==
|
||||
(m_ReverseOutput ^ Orientation(outRec, m_UseFullRange)))
|
||||
|
@ -1579,8 +1592,10 @@ void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt)
|
|||
e1->outIdx = -1;
|
||||
e2->outIdx = -1;
|
||||
}
|
||||
else if (e1->outIdx < e2->outIdx)
|
||||
AppendPolygon(e1, e2);
|
||||
else
|
||||
AppendPolygon( e1, e2 );
|
||||
AppendPolygon(e2, e1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -1949,6 +1964,17 @@ OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2)
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2)
|
||||
{
|
||||
do
|
||||
{
|
||||
outRec1 = outRec1->FirstLeft;
|
||||
if (outRec1 == outRec2) return true;
|
||||
} while (outRec1);
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
|
||||
{
|
||||
//get the start and ends of both output polygons ...
|
||||
|
@ -1956,8 +1982,8 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
|
|||
OutRec *outRec2 = m_PolyOuts[e2->outIdx];
|
||||
|
||||
OutRec *holeStateRec;
|
||||
if (outRec1->FirstLeft == outRec2) holeStateRec = outRec2;
|
||||
else if (outRec2->FirstLeft == outRec1) holeStateRec = outRec1;
|
||||
if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2;
|
||||
else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1;
|
||||
else holeStateRec = GetLowermostRec(outRec1, outRec2);
|
||||
|
||||
OutPt* p1_lft = outRec1->pts;
|
||||
|
@ -2077,6 +2103,7 @@ void Clipper::DisposeBottomPt(OutRec &outRec)
|
|||
next->prev = prev;
|
||||
prev->next = next;
|
||||
outRec.bottomPt = next;
|
||||
FixupOutPolygon(outRec);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -2310,8 +2337,7 @@ void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2)
|
|||
|
||||
TEdge* GetNextInAEL(TEdge *e, Direction dir)
|
||||
{
|
||||
if( dir == dLeftToRight ) return e->nextInAEL;
|
||||
else return e->prevInAEL;
|
||||
return dir == dLeftToRight ? e->nextInAEL : e->prevInAEL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -2520,7 +2546,7 @@ void Clipper::BuildIntersectList(const long64 botY, const long64 topY)
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool Process1Before2(IntersectNode &node1, IntersectNode &node2)
|
||||
bool ProcessParam1BeforeParam2(IntersectNode &node1, IntersectNode &node2)
|
||||
{
|
||||
bool result;
|
||||
if (node1.pt.Y == node2.pt.Y)
|
||||
|
@ -2528,12 +2554,12 @@ bool Process1Before2(IntersectNode &node1, IntersectNode &node2)
|
|||
if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1)
|
||||
{
|
||||
result = node2.pt.X > node1.pt.X;
|
||||
if (node2.edge1->dx > 0) return !result; else return result;
|
||||
return node2.edge1->dx > 0 ? !result : result;
|
||||
}
|
||||
else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2)
|
||||
{
|
||||
result = node2.pt.X > node1.pt.X;
|
||||
if (node2.edge2->dx > 0) return !result; else return result;
|
||||
return node2.edge2->dx > 0 ? !result : result;
|
||||
}
|
||||
else return node2.pt.X > node1.pt.X;
|
||||
}
|
||||
|
@ -2549,7 +2575,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
|
|||
newNode->pt = pt;
|
||||
newNode->next = 0;
|
||||
if( !m_IntersectNodes ) m_IntersectNodes = newNode;
|
||||
else if( Process1Before2(*newNode, *m_IntersectNodes) )
|
||||
else if( ProcessParam1BeforeParam2(*newNode, *m_IntersectNodes) )
|
||||
{
|
||||
newNode->next = m_IntersectNodes;
|
||||
m_IntersectNodes = newNode;
|
||||
|
@ -2557,7 +2583,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
|
|||
else
|
||||
{
|
||||
IntersectNode* iNode = m_IntersectNodes;
|
||||
while( iNode->next && Process1Before2(*iNode->next, *newNode) )
|
||||
while( iNode->next && ProcessParam1BeforeParam2(*iNode->next, *newNode) )
|
||||
iNode = iNode->next;
|
||||
newNode->next = iNode->next;
|
||||
iNode->next = newNode;
|
||||
|
@ -2859,8 +2885,7 @@ bool Clipper::FixupIntersections()
|
|||
|
||||
bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2)
|
||||
{
|
||||
if (e2.xcurr == e1.xcurr) return e2.dx > e1.dx;
|
||||
else return e2.xcurr < e1.xcurr;
|
||||
return e2.xcurr == e1.xcurr ? e2.dx > e1.dx : e2.xcurr < e1.xcurr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -3029,8 +3054,9 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
|
|||
//outRec2 is contained by outRec1 ...
|
||||
outRec2->isHole = !outRec1->isHole;
|
||||
outRec2->FirstLeft = outRec1;
|
||||
if (outRec2->isHole == Orientation(outRec2, m_UseFullRange))
|
||||
ReversePolyPtLinks(*outRec2->pts);
|
||||
if (outRec2->isHole ==
|
||||
(m_ReverseOutput ^ Orientation(outRec2, m_UseFullRange)))
|
||||
ReversePolyPtLinks(*outRec2->pts);
|
||||
} else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange))
|
||||
{
|
||||
//outRec1 is contained by outRec2 ...
|
||||
|
@ -3038,8 +3064,9 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
|
|||
outRec1->isHole = !outRec2->isHole;
|
||||
outRec2->FirstLeft = outRec1->FirstLeft;
|
||||
outRec1->FirstLeft = outRec2;
|
||||
if (outRec1->isHole == Orientation(outRec1, m_UseFullRange))
|
||||
ReversePolyPtLinks(*outRec1->pts);
|
||||
if (outRec1->isHole ==
|
||||
(m_ReverseOutput ^ Orientation(outRec1, m_UseFullRange)))
|
||||
ReversePolyPtLinks(*outRec1->pts);
|
||||
//make sure any contained holes now link to the correct polygon ...
|
||||
if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2);
|
||||
} else
|
||||
|
@ -3063,6 +3090,12 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
|
|||
//now cleanup redundant edges too ...
|
||||
FixupOutPolygon(*outRec1);
|
||||
FixupOutPolygon(*outRec2);
|
||||
|
||||
if (Orientation(outRec1, m_UseFullRange) != (Area(*outRec1, m_UseFullRange) > 0))
|
||||
DisposeBottomPt(*outRec1);
|
||||
if (Orientation(outRec2, m_UseFullRange) != (Area(*outRec2, m_UseFullRange) > 0))
|
||||
DisposeBottomPt(*outRec2);
|
||||
|
||||
} else
|
||||
{
|
||||
//joined 2 polygons together ...
|
||||
|
@ -3099,16 +3132,16 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ReversePoints(Polygon& p)
|
||||
void ReversePolygon(Polygon& p)
|
||||
{
|
||||
std::reverse(p.begin(), p.end());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ReversePoints(Polygons& p)
|
||||
void ReversePolygons(Polygons& p)
|
||||
{
|
||||
for (Polygons::size_type i = 0; i < p.size(); ++i)
|
||||
ReversePoints(p[i]);
|
||||
ReversePolygon(p[i]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -3126,12 +3159,13 @@ struct DoublePoint
|
|||
Polygon BuildArc(const IntPoint &pt,
|
||||
const double a1, const double a2, const double r)
|
||||
{
|
||||
int steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1)));
|
||||
Polygon result(steps);
|
||||
int n = steps - 1;
|
||||
double da = (a2 - a1) / n;
|
||||
long64 steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1)));
|
||||
if (steps > 0x100000) steps = 0x100000;
|
||||
int n = (unsigned)steps;
|
||||
Polygon result(n);
|
||||
double da = (a2 - a1) / (n -1);
|
||||
double a = a1;
|
||||
for (int i = 0; i <= n; ++i)
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
result[i].X = pt.X + Round(std::cos(a)*r);
|
||||
result[i].Y = pt.Y + Round(std::sin(a)*r);
|
||||
|
@ -3259,7 +3293,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
|
|||
if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative))
|
||||
{
|
||||
out_polys.erase(out_polys.begin());
|
||||
ReversePoints(out_polys);
|
||||
ReversePolygons(out_polys);
|
||||
|
||||
} else
|
||||
out_polys.clear();
|
||||
|
@ -3286,23 +3320,23 @@ void DoSquare(double mul = 1.0)
|
|||
(long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta));
|
||||
if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0)
|
||||
{
|
||||
double a1 = std::atan2(normals[m_k].Y, normals[m_k].X);
|
||||
double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X);
|
||||
a1 = std::fabs(a2 - a1);
|
||||
if (a1 > pi) a1 = pi * 2 - a1;
|
||||
double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul);
|
||||
pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx),
|
||||
(long64)(pt1.Y + normals[m_k].X * dx));
|
||||
AddPoint(pt1);
|
||||
pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx),
|
||||
(long64)(pt2.Y -normals[m_j].X * dx));
|
||||
AddPoint(pt2);
|
||||
double a1 = std::atan2(normals[m_k].Y, normals[m_k].X);
|
||||
double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X);
|
||||
a1 = std::fabs(a2 - a1);
|
||||
if (a1 > pi) a1 = pi * 2 - a1;
|
||||
double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul);
|
||||
pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx),
|
||||
(long64)(pt1.Y + normals[m_k].X * dx));
|
||||
AddPoint(pt1);
|
||||
pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx),
|
||||
(long64)(pt2.Y -normals[m_j].X * dx));
|
||||
AddPoint(pt2);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPoint(pt1);
|
||||
AddPoint(m_p[m_i][m_j]);
|
||||
AddPoint(pt2);
|
||||
AddPoint(pt1);
|
||||
AddPoint(m_p[m_i][m_j]);
|
||||
AddPoint(pt2);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -3373,25 +3407,25 @@ void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys)
|
||||
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType)
|
||||
{
|
||||
Clipper c;
|
||||
c.AddPolygon(in_poly, ptSubject);
|
||||
c.Execute(ctUnion, out_polys);
|
||||
c.Execute(ctUnion, out_polys, fillType, fillType);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys)
|
||||
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType)
|
||||
{
|
||||
Clipper c;
|
||||
c.AddPolygons(in_polys, ptSubject);
|
||||
c.Execute(ctUnion, out_polys);
|
||||
c.Execute(ctUnion, out_polys, fillType, fillType);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SimplifyPolygons(Polygons &polys)
|
||||
void SimplifyPolygons(Polygons &polys, PolyFillType fillType)
|
||||
{
|
||||
SimplifyPolygons(polys, polys);
|
||||
SimplifyPolygons(polys, polys, fillType);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* *
|
||||
* Author : Angus Johnson *
|
||||
* Version : 4.8.3 *
|
||||
* Date : 27 May 2012 *
|
||||
* Version : 4.8.9 *
|
||||
* Date : 25 September 2012 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2012 *
|
||||
* *
|
||||
|
@ -79,12 +79,12 @@ bool Orientation(const Polygon &poly);
|
|||
double Area(const Polygon &poly);
|
||||
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
|
||||
double delta, JoinType jointype = jtSquare, double MiterLimit = 2);
|
||||
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys);
|
||||
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys);
|
||||
void SimplifyPolygons(Polygons &polys);
|
||||
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
|
||||
|
||||
void ReversePoints(Polygon& p);
|
||||
void ReversePoints(Polygons& p);
|
||||
void ReversePolygon(Polygon& p);
|
||||
void ReversePolygons(Polygons& p);
|
||||
|
||||
//used internally ...
|
||||
enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 };
|
||||
|
|
|
@ -26,10 +26,13 @@
|
|||
// http://www.cs.man.ac.uk/aig/staff/alan/software/
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <Geometry/point3d.hxx>
|
||||
#include <Geometry/poly_support.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
|
@ -40,6 +43,7 @@
|
|||
#include "point2d.hxx"
|
||||
|
||||
using std::endl;
|
||||
using std::cout;
|
||||
|
||||
// Constructor
|
||||
TGPolygon::TGPolygon( void )
|
||||
|
@ -395,10 +399,10 @@ typedef enum {
|
|||
} clip_op;
|
||||
|
||||
|
||||
//#define FIXEDPT (10000000000000)
|
||||
#define FIXEDPT (10000000000000000)
|
||||
#define FIXED1M ( 90090)
|
||||
|
||||
|
||||
static ClipperLib::IntPoint MakeClipperPoint( Point3D pt )
|
||||
{
|
||||
ClipperLib::long64 x, y;
|
||||
|
@ -451,19 +455,20 @@ void make_clipper_poly( const TGPolygon& in, ClipperLib::Polygons *out )
|
|||
// holes need to be orientation: false
|
||||
if ( Orientation( contour ) ) {
|
||||
//SG_LOG(SG_GENERAL, SG_INFO, "Building clipper poly - hole contour needs to be reversed" );
|
||||
ReversePoints( contour );
|
||||
ReversePolygon( contour );
|
||||
}
|
||||
} else {
|
||||
// boundaries need to be orientation: true
|
||||
if ( !Orientation( contour ) ) {
|
||||
//SG_LOG(SG_GENERAL, SG_INFO, "Building clipper poly - boundary contour needs to be reversed" );
|
||||
ReversePoints( contour );
|
||||
ReversePolygon( contour );
|
||||
}
|
||||
}
|
||||
out->push_back(contour);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void make_tg_poly_from_clipper_ex( const ClipperLib::ExPolygons& in, TGPolygon *out )
|
||||
{
|
||||
int res_contour = 0;
|
||||
|
@ -496,6 +501,7 @@ void make_tg_poly_from_clipper_ex( const ClipperLib::ExPolygons& in, TGPolygon *
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void make_tg_poly_from_clipper( const ClipperLib::Polygons& in, TGPolygon *out )
|
||||
{
|
||||
|
@ -523,6 +529,7 @@ void make_tg_poly_from_clipper( const ClipperLib::Polygons& in, TGPolygon *out )
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
ClipperLib::Polygons clipper_simplify( ClipperLib::ExPolygons &in )
|
||||
{
|
||||
ClipperLib::Polygons out;
|
||||
|
@ -535,7 +542,7 @@ ClipperLib::Polygons clipper_simplify( ClipperLib::ExPolygons &in )
|
|||
// first the boundary
|
||||
contour = pg->outer;
|
||||
if ( !Orientation( contour ) ) {
|
||||
ReversePoints( contour );
|
||||
ReversePolygon( contour );
|
||||
}
|
||||
out.push_back( contour );
|
||||
|
||||
|
@ -544,7 +551,7 @@ ClipperLib::Polygons clipper_simplify( ClipperLib::ExPolygons &in )
|
|||
{
|
||||
contour = pg->holes[j];
|
||||
if ( Orientation( contour ) ) {
|
||||
ReversePoints( contour );
|
||||
ReversePolygon( contour );
|
||||
}
|
||||
out.push_back( contour );
|
||||
}
|
||||
|
@ -555,6 +562,7 @@ ClipperLib::Polygons clipper_simplify( ClipperLib::ExPolygons &in )
|
|||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const TGPolygon& clip )
|
||||
{
|
||||
|
@ -566,15 +574,15 @@ TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const
|
|||
ClipperLib::Polygons clipper_clip;
|
||||
make_clipper_poly( clip, &clipper_clip );
|
||||
|
||||
ClipperLib::ExPolygons clipper_result;
|
||||
ClipperLib::Polygons clipper_result;
|
||||
|
||||
ClipperLib::ClipType op;
|
||||
if ( poly_op == POLY_DIFF ) {
|
||||
op = ClipperLib::ctDifference;
|
||||
op = ClipperLib::ctDifference;
|
||||
} else if ( poly_op == POLY_INT ) {
|
||||
op = ClipperLib::ctIntersection;
|
||||
op = ClipperLib::ctIntersection;
|
||||
} else if ( poly_op == POLY_XOR ) {
|
||||
op = ClipperLib::ctXor;
|
||||
op = ClipperLib::ctXor;
|
||||
} else if ( poly_op == POLY_UNION ) {
|
||||
op = ClipperLib::ctUnion;
|
||||
} else {
|
||||
|
@ -582,16 +590,13 @@ TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const
|
|||
}
|
||||
|
||||
ClipperLib::Clipper c;
|
||||
c.Clear();
|
||||
c.AddPolygons(clipper_subject, ClipperLib::ptSubject);
|
||||
c.AddPolygons(clipper_clip, ClipperLib::ptClip);
|
||||
c.Clear();
|
||||
c.AddPolygons(clipper_subject, ClipperLib::ptSubject);
|
||||
c.AddPolygons(clipper_clip, ClipperLib::ptClip);
|
||||
|
||||
c.Execute(op, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
|
||||
c.Execute(op, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
|
||||
|
||||
// verify each result is simple
|
||||
ClipperLib::Polygons simple_result = clipper_simplify( clipper_result );
|
||||
|
||||
make_tg_poly_from_clipper( simple_result, &result );
|
||||
make_tg_poly_from_clipper( clipper_result, &result );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -633,26 +638,80 @@ void tgPolygonFreeClipperAccumulator( void )
|
|||
clipper_accumulator.clear();
|
||||
}
|
||||
|
||||
|
||||
void tgPolygonAddToClipperAccumulator( const TGPolygon& subject )
|
||||
void tgPolygonDumpAccumulator( char* ds, char* layer, char* name )
|
||||
{
|
||||
void* ds_id = tgShapefileOpenDatasource( ds );
|
||||
void* l_id = tgShapefileOpenLayer( ds_id, layer );
|
||||
TGPolygon accum;
|
||||
|
||||
make_tg_poly_from_clipper( clipper_accumulator, &accum );
|
||||
tgShapefileCreateFeature( ds_id, l_id, accum, name );
|
||||
|
||||
// close after each write
|
||||
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||
}
|
||||
|
||||
void tgPolygonAddToClipperAccumulator( const TGPolygon& subject, bool dump )
|
||||
{
|
||||
std::ofstream subjectFile, clipFile, resultFile;
|
||||
|
||||
ClipperLib::Polygons clipper_subject;
|
||||
make_clipper_poly( subject, &clipper_subject );
|
||||
|
||||
ClipperLib::ExPolygons clipper_result;
|
||||
|
||||
ClipperLib::Clipper c;
|
||||
c.Clear();
|
||||
c.AddPolygons(clipper_subject, ClipperLib::ptSubject);
|
||||
c.AddPolygons(clipper_accumulator, ClipperLib::ptClip);
|
||||
|
||||
c.Execute(ClipperLib::ctUnion, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
|
||||
if (dump) {
|
||||
subjectFile.open ("subject.txt");
|
||||
subjectFile << clipper_subject;
|
||||
subjectFile.close();
|
||||
|
||||
// verify each result is simple
|
||||
ClipperLib::Polygons simple_result = clipper_simplify( clipper_result );
|
||||
clipFile.open ("clip.txt");
|
||||
clipFile << clipper_accumulator;
|
||||
clipFile.close();
|
||||
}
|
||||
|
||||
clipper_accumulator.clear();
|
||||
clipper_accumulator = simple_result;
|
||||
if ( !c.Execute(ClipperLib::ctUnion, clipper_accumulator, ClipperLib::pftNonZero, ClipperLib::pftNonZero) ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Add to Accumulator returned FALSE" );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (dump) {
|
||||
resultFile.open ("result.txt");
|
||||
resultFile << clipper_accumulator;
|
||||
resultFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void clipper_to_shapefile( ClipperLib::Polygons polys, char* ds )
|
||||
{
|
||||
ClipperLib::Polygons contour;
|
||||
TGPolygon tgcontour;
|
||||
char layer[32];
|
||||
|
||||
void* ds_id = tgShapefileOpenDatasource( ds );
|
||||
|
||||
for (unsigned int i = 0; i < polys.size(); ++i) {
|
||||
if ( Orientation( polys[i] ) ) {
|
||||
sprintf( layer, "%04d_hole", i );
|
||||
} else {
|
||||
sprintf( layer, "%04d_boundary", i );
|
||||
}
|
||||
|
||||
void* l_id = tgShapefileOpenLayer( ds_id, layer );
|
||||
contour.clear();
|
||||
contour.push_back( polys[i] );
|
||||
|
||||
tgcontour.erase();
|
||||
make_tg_poly_from_clipper( contour, &tgcontour );
|
||||
|
||||
tgShapefileCreateFeature( ds_id, l_id, tgcontour, "contour" );
|
||||
}
|
||||
|
||||
// close after each write
|
||||
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||
}
|
||||
|
||||
TGPolygon tgPolygonDiffClipperWithAccumulator( const TGPolygon& subject )
|
||||
|
@ -662,19 +721,20 @@ TGPolygon tgPolygonDiffClipperWithAccumulator( const TGPolygon& subject )
|
|||
ClipperLib::Polygons clipper_subject;
|
||||
make_clipper_poly( subject, &clipper_subject );
|
||||
|
||||
ClipperLib::ExPolygons clipper_result;
|
||||
ClipperLib::Polygons clipper_result;
|
||||
|
||||
ClipperLib::Clipper c;
|
||||
c.Clear();
|
||||
c.AddPolygons(clipper_subject, ClipperLib::ptSubject);
|
||||
c.AddPolygons(clipper_accumulator, ClipperLib::ptClip);
|
||||
|
||||
c.Execute(ClipperLib::ctDifference, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
|
||||
if ( !c.Execute(ClipperLib::ctDifference, clipper_result, ClipperLib::pftNonZero, ClipperLib::pftNonZero) )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Diff With Accumulator returned FALSE" );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// verify each result is simple
|
||||
ClipperLib::Polygons simple_result = clipper_simplify( clipper_result );
|
||||
|
||||
make_tg_poly_from_clipper( simple_result, &result );
|
||||
make_tg_poly_from_clipper( clipper_result, &result );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -695,6 +755,16 @@ TGPolygon tgPolygonUnionClipper( const TGPolygon& subject, const TGPolygon& clip
|
|||
return polygon_clip_clipper( POLY_UNION, subject, clip );
|
||||
}
|
||||
|
||||
void tgPolygonDumpClipper(const TGPolygon &poly, char* file)
|
||||
{
|
||||
ClipperLib::Polygons clipper_subject;
|
||||
make_clipper_poly( poly, &clipper_subject );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "DUMP POLY" );
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, clipper_subject );
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\n" );
|
||||
}
|
||||
|
||||
// canonify the polygon winding, outer contour must be anti-clockwise,
|
||||
// all inner contours must be clockwise.
|
||||
TGPolygon polygon_canonify( const TGPolygon& in_poly ) {
|
||||
|
|
|
@ -258,9 +258,13 @@ TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip );
|
|||
|
||||
void tgPolygonInitClipperAccumulator( void );
|
||||
void tgPolygonFreeClipperAccumulator( void );
|
||||
void tgPolygonAddToClipperAccumulator( const TGPolygon& subject );
|
||||
void tgPolygonDumpAccumulator( char* ds, char* layer, char*name );
|
||||
void tgPolygonAddToClipperAccumulator( const TGPolygon& subject, bool dump );
|
||||
TGPolygon tgPolygonDiffClipperWithAccumulator( const TGPolygon& subject );
|
||||
|
||||
// Save clipper to shapefile
|
||||
void clipper_to_shapefile( ClipperLib::Polygons polys, char* datasource );
|
||||
|
||||
// Difference
|
||||
TGPolygon tgPolygonDiffClipper( const TGPolygon& subject, const TGPolygon& clip );
|
||||
|
||||
|
@ -276,6 +280,8 @@ TGPolygon tgPolygonExpand(const TGPolygon &poly, double delta);
|
|||
// Simplify
|
||||
TGPolygon tgPolygonSimplify(const TGPolygon &poly);
|
||||
|
||||
void tgPolygonDumpClipper(const TGPolygon &poly);
|
||||
|
||||
// Output
|
||||
std::ostream &operator<<(std::ostream &output, const TGPolygon &poly);
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@ add_executable(e00lines
|
|||
target_link_libraries(e00lines
|
||||
e00
|
||||
Polygon Geometry Output poly2tri vpf
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS e00lines RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -6,8 +6,9 @@ add_executable(gshhs
|
|||
|
||||
target_link_libraries(gshhs
|
||||
Polygon Geometry Output poly2tri
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS gshhs RUNTIME DESTINATION bin)
|
||||
|
@ -17,8 +18,9 @@ add_executable(gshhs_debug
|
|||
|
||||
target_link_libraries(gshhs_debug
|
||||
Polygon Geometry Output poly2tri
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS gshhs_debug RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -193,6 +193,8 @@ void processLineStringWithTextureInfo(OGRLineString* poGeometry,
|
|||
double pt_x = 0.0f, pt_y = 0.0f;
|
||||
int i, j, numPoints, numSegs;
|
||||
double max_dist;
|
||||
double min_dist;
|
||||
double cur_dist;
|
||||
|
||||
numPoints = poGeometry->getNumPoints();
|
||||
if (numPoints < 2) {
|
||||
|
@ -201,6 +203,8 @@ void processLineStringWithTextureInfo(OGRLineString* poGeometry,
|
|||
}
|
||||
|
||||
max_dist = (double)width * 10.0f;
|
||||
min_dist = (double)width * 1.5f;
|
||||
cur_dist = 0.0f;
|
||||
|
||||
// because vector data can generate adjacent polys, lets stretch the two enpoints by a little bit
|
||||
p0 = Point3D(poGeometry->getX(0),poGeometry->getY(0),0);
|
||||
|
@ -226,10 +230,16 @@ void processLineStringWithTextureInfo(OGRLineString* poGeometry,
|
|||
geo_direct_wgs_84( p0.y(), p0.x(), heading, dist*(j+1), &pt_y, &pt_x, &az2 );
|
||||
line.addPoint( Point3D( pt_x, pt_y, 0.0f ) );
|
||||
}
|
||||
cur_dist = 0.0f;
|
||||
}
|
||||
else if (dist + cur_dist < max_dist)
|
||||
{
|
||||
cur_dist += dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
line.addPoint(p1);
|
||||
line.addPoint( p1 );
|
||||
cur_dist = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@ add_executable(photo
|
|||
|
||||
target_link_libraries(photo
|
||||
Polygon Geometry Array Output poly2tri
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS photo RUNTIME DESTINATION bin)
|
||||
|
@ -14,8 +15,9 @@ add_executable(wgs84offset
|
|||
wgs84offset.cxx)
|
||||
|
||||
target_link_libraries(wgs84offset
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS wgs84offset RUNTIME DESTINATION bin)
|
||||
|
@ -25,8 +27,9 @@ add_executable(findcorners
|
|||
findcorners.cxx)
|
||||
|
||||
target_link_libraries(findcorners
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS findcorners RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -2,8 +2,9 @@ add_executable(shape-decode shape-decode.cxx)
|
|||
|
||||
target_link_libraries(shape-decode
|
||||
shape Polygon Geometry Output poly2tri vpf
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS shape-decode RUNTIME DESTINATION bin)
|
||||
|
@ -12,8 +13,9 @@ add_executable(noaa-decode noaa-decode.cxx)
|
|||
|
||||
target_link_libraries(noaa-decode
|
||||
shape Polygon Geometry Output poly2tri vpf
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS noaa-decode RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -3,8 +3,9 @@ add_executable(tgvpf tgvpf.cxx)
|
|||
|
||||
target_link_libraries(tgvpf
|
||||
Polygon Geometry Output poly2tri vpf
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${RT_LIBRARY})
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${RT_LIBRARY})
|
||||
|
||||
install(TARGETS tgvpf RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -3,8 +3,9 @@ add_executable(tguserdef tguserdef.cxx)
|
|||
|
||||
target_link_libraries(tguserdef
|
||||
Polygon Geometry Output poly2tri
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
${GDAL_LIBRARY}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
)
|
||||
|
||||
install(TARGETS tguserdef RUNTIME DESTINATION bin)
|
||||
|
|
Loading…
Reference in a new issue