From b44c6c00d00f93d0a1eaa9cb8560b7e0ea931e44 Mon Sep 17 00:00:00 2001 From: Peter Sadrozinski Date: Fri, 28 Sep 2012 19:51:13 -0400 Subject: [PATCH] - 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. --- src/BuildTiles/CMakeLists.txt | 6 +- src/BuildTiles/Main/CMakeLists.txt | 16 ++ src/BuildTiles/Main/cliptst.cxx | 319 +++++++++++++++++++++++++++++ src/BuildTiles/Main/construct.cxx | 173 ++++++++++++---- src/BuildTiles/Main/construct.hxx | 5 +- src/BuildTiles/Main/main.cxx | 15 +- src/Lib/Geometry/util.cxx | 180 ++++++++++++++++ src/Lib/Polygon/clipper.cpp | 168 +++++++++------ src/Lib/Polygon/clipper.hpp | 14 +- src/Lib/Polygon/polygon.cxx | 136 +++++++++--- src/Lib/Polygon/polygon.hxx | 8 +- src/Prep/E00Lines/CMakeLists.txt | 5 +- src/Prep/GSHHS/CMakeLists.txt | 10 +- src/Prep/OGRDecode/ogr-decode.cxx | 14 +- src/Prep/Photo/CMakeLists.txt | 15 +- src/Prep/ShapeFile/CMakeLists.txt | 10 +- src/Prep/TGVPF/CMakeLists.txt | 9 +- src/Prep/UserDef/CMakeLists.txt | 7 +- 18 files changed, 931 insertions(+), 179 deletions(-) create mode 100644 src/BuildTiles/Main/cliptst.cxx diff --git a/src/BuildTiles/CMakeLists.txt b/src/BuildTiles/CMakeLists.txt index f49c3a24..692337a1 100644 --- a/src/BuildTiles/CMakeLists.txt +++ b/src/BuildTiles/CMakeLists.txt @@ -4,6 +4,6 @@ include_directories(${PROJECT_SOURCE_DIR}/src/Lib) include_directories(${PROJECT_SOURCE_DIR}/src/BuildTiles) add_subdirectory(Osgb36) -add_subdirectory(Parallel) -add_subdirectory(Match) -add_subdirectory(Main) +add_subdirectory(Parallel) +add_subdirectory(Match) +add_subdirectory(Main) diff --git a/src/BuildTiles/Main/CMakeLists.txt b/src/BuildTiles/Main/CMakeLists.txt index 94fe3d16..2b93962c 100644 --- a/src/BuildTiles/Main/CMakeLists.txt +++ b/src/BuildTiles/Main/CMakeLists.txt @@ -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} ) diff --git a/src/BuildTiles/Main/cliptst.cxx b/src/BuildTiles/Main/cliptst.cxx new file mode 100644 index 00000000..8ebe269f --- /dev/null +++ b/src/BuildTiles/Main/cliptst.cxx @@ -0,0 +1,319 @@ +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//#include "windows.h" +//#include + +//--------------------------------------------------------------------------- + +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; +} +//--------------------------------------------------------------------------- diff --git a/src/BuildTiles/Main/construct.cxx b/src/BuildTiles/Main/construct.cxx index bc35beb2..eb5154f2 100644 --- a/src/BuildTiles/Main/construct.cxx +++ b/src/BuildTiles/Main/construct.cxx @@ -91,15 +91,42 @@ TGConstruct::~TGConstruct() { nodes.clear(); } -void TGConstruct::set_debug( std::string path, std::vector defs ) +void TGConstruct::set_debug( std::string path, std::vector area_defs, std::vector 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 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 { diff --git a/src/BuildTiles/Main/construct.hxx b/src/BuildTiles/Main/construct.hxx index 92edb783..fc20157f 100644 --- a/src/BuildTiles/Main/construct.hxx +++ b/src/BuildTiles/Main/construct.hxx @@ -271,6 +271,7 @@ private: bool debug_all; // list of shapes to dump during debug + std::vector debug_areas; std::vector 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 defs ); + void set_debug( std::string path, std::vector area_defs, std::vector shape_defs ); }; diff --git a/src/BuildTiles/Main/main.cxx b/src/BuildTiles/Main/main.cxx index 8eeaf5cb..5f3ddf00 100644 --- a/src/BuildTiles/Main/main.cxx +++ b/src/BuildTiles/Main/main.cxx @@ -168,7 +168,8 @@ int main(int argc, char **argv) { long tile_id = -1; string debug_dir = "."; - vector debug_defs; + vector debug_shape_defs; + vector 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; diff --git a/src/Lib/Geometry/util.cxx b/src/Lib/Geometry/util.cxx index 376b59eb..7c1d3912 100644 --- a/src/Lib/Geometry/util.cxx +++ b/src/Lib/Geometry/util.cxx @@ -16,6 +16,16 @@ #include +// 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 +#include + +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +typedef Kernel::Point_2 Point_2; +typedef CGAL::Segment_2 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 *ipoint = CGAL::object_cast >(&result)) { + // handle the point intersection case with *ipoint. + return true; + } else { + if (const CGAL::Segment_2 *iseg = CGAL::object_cast >(&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= (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 - AppendPolygon( e1, e2 ); + else if (e1->outIdx < e2->outIdx) + AppendPolygon(e1, e2); + else + 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); } //------------------------------------------------------------------------------ diff --git a/src/Lib/Polygon/clipper.hpp b/src/Lib/Polygon/clipper.hpp index 35ec6c97..351ac79c 100644 --- a/src/Lib/Polygon/clipper.hpp +++ b/src/Lib/Polygon/clipper.hpp @@ -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 }; diff --git a/src/Lib/Polygon/polygon.cxx b/src/Lib/Polygon/polygon.cxx index b15567ed..a54e7880 100644 --- a/src/Lib/Polygon/polygon.cxx +++ b/src/Lib/Polygon/polygon.cxx @@ -26,10 +26,13 @@ // http://www.cs.man.ac.uk/aig/staff/alan/software/ // +#include +#include #include #include #include +#include #include #include @@ -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,16 +542,16 @@ ClipperLib::Polygons clipper_simplify( ClipperLib::ExPolygons &in ) // first the boundary contour = pg->outer; if ( !Orientation( contour ) ) { - ReversePoints( contour ); + ReversePolygon( contour ); } out.push_back( contour ); - + // then the holes for (unsigned int j = 0; j < pg->holes.size(); j++) { 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 ) { diff --git a/src/Lib/Polygon/polygon.hxx b/src/Lib/Polygon/polygon.hxx index 3c25698e..f36d0fc6 100644 --- a/src/Lib/Polygon/polygon.hxx +++ b/src/Lib/Polygon/polygon.hxx @@ -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); diff --git a/src/Prep/E00Lines/CMakeLists.txt b/src/Prep/E00Lines/CMakeLists.txt index 9036611a..0e73952b 100644 --- a/src/Prep/E00Lines/CMakeLists.txt +++ b/src/Prep/E00Lines/CMakeLists.txt @@ -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) diff --git a/src/Prep/GSHHS/CMakeLists.txt b/src/Prep/GSHHS/CMakeLists.txt index 3b848d8a..0df8f93b 100644 --- a/src/Prep/GSHHS/CMakeLists.txt +++ b/src/Prep/GSHHS/CMakeLists.txt @@ -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) diff --git a/src/Prep/OGRDecode/ogr-decode.cxx b/src/Prep/OGRDecode/ogr-decode.cxx index c6d641ad..a1dcf92a 100644 --- a/src/Prep/OGRDecode/ogr-decode.cxx +++ b/src/Prep/OGRDecode/ogr-decode.cxx @@ -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); @@ -225,11 +229,17 @@ 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; } } diff --git a/src/Prep/Photo/CMakeLists.txt b/src/Prep/Photo/CMakeLists.txt index e653f40c..1bea6dca 100644 --- a/src/Prep/Photo/CMakeLists.txt +++ b/src/Prep/Photo/CMakeLists.txt @@ -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) diff --git a/src/Prep/ShapeFile/CMakeLists.txt b/src/Prep/ShapeFile/CMakeLists.txt index ec565bc9..05afc256 100644 --- a/src/Prep/ShapeFile/CMakeLists.txt +++ b/src/Prep/ShapeFile/CMakeLists.txt @@ -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) diff --git a/src/Prep/TGVPF/CMakeLists.txt b/src/Prep/TGVPF/CMakeLists.txt index 02989cdd..5b28cfb3 100644 --- a/src/Prep/TGVPF/CMakeLists.txt +++ b/src/Prep/TGVPF/CMakeLists.txt @@ -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) diff --git a/src/Prep/UserDef/CMakeLists.txt b/src/Prep/UserDef/CMakeLists.txt index 81b5de01..d626562f 100644 --- a/src/Prep/UserDef/CMakeLists.txt +++ b/src/Prep/UserDef/CMakeLists.txt @@ -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)