From 5f83fe82c6d100635292e4902e1d5a6b0a16905c Mon Sep 17 00:00:00 2001 From: Peter Sadrozinski Date: Tue, 14 Aug 2012 20:31:15 -0400 Subject: [PATCH] Implemented shape file debug capability via command line options: --debug-dir=pathname points to the debug root directory. each tile will create a sub directory in this existing directory. (default is '.') --debug-shapes=tileid:shape1,shape2,etc.. lists the shapes to debug within a tile example: if the tesselator crashes in shape id '123', you can rerun with --debug-shapes=2678440:337 implemented the same bounding box optimization from tesselate in FixTJunctions. Also fixed a bounding box issue that could cause some elevation points to be missed. brought in the latest version of clipper - and moved the #define to the construct header some debug cleanup (especially in polygon loading) --- src/BuildTiles/Main/construct.cxx | 143 ++++++++++++++++++------------ src/BuildTiles/Main/construct.hxx | 43 +++++++-- src/BuildTiles/Main/main.cxx | 31 +++++-- src/Lib/Geometry/point3d.hxx | 4 +- src/Lib/Geometry/poly_extra.cxx | 54 +++-------- src/Lib/Geometry/poly_support.cxx | 48 ++++++---- src/Lib/Geometry/poly_support.hxx | 2 +- src/Lib/Geometry/tg_nodes.cxx | 6 +- src/Lib/Polygon/clipper.cpp | 73 +++++++-------- src/Lib/Polygon/clipper.hpp | 4 +- src/Lib/Polygon/polygon.cxx | 21 +++++ src/Lib/Polygon/polygon.hxx | 14 +-- 12 files changed, 259 insertions(+), 184 deletions(-) diff --git a/src/BuildTiles/Main/construct.cxx b/src/BuildTiles/Main/construct.cxx index c3f1d5ef..f75d87c1 100644 --- a/src/BuildTiles/Main/construct.cxx +++ b/src/BuildTiles/Main/construct.cxx @@ -25,6 +25,9 @@ # include #endif +#include +#include + #include #include @@ -53,7 +56,6 @@ double gSnap = 0.00000001; // approx 1 mm static const double cover_size = 1.0 / 120.0; static const double half_cover_size = cover_size * 0.5; -#define USE_CLIPPER (0) // If we don't offset land use squares by some amount, then we can get // land use square boundaries coinciding with tile boundaries. @@ -65,20 +67,12 @@ static const double half_cover_size = cover_size * 0.5; // problem. static const double quarter_cover_size = cover_size * 0.25; - -// For debug: -void* ds_id = NULL; // If we are going to build shapefiles -void* l_id = NULL; // datasource and layer IDs -char ds_name[128]; // need to clean this up and add cmdline options -char layer_name[128]; -char feature_name[128]; - - // Constructor TGConstruct::TGConstruct(): useUKGrid(false), writeSharedEdges(true), - useOwnSharedEdges(false) + useOwnSharedEdges(false), + ds_id((void*)-1) { } @@ -94,6 +88,64 @@ TGConstruct::~TGConstruct() { nodes.clear(); } +void TGConstruct::set_debug( std::string path, std::vector 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]; + 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); + std::stringstream ss(dsd); + int i; + + while (ss >> i) + { + SG_LOG(SG_GENERAL, SG_ALERT, "Adding debug file " << i); + + debug_shapes.push_back(i); + + if (ss.peek() == ',') + ss.ignore(); + } + } + } +} + +bool TGConstruct::IsDebugShape( unsigned int id ) +{ + bool is_debug = false; + + for (unsigned int i=0; i> contours; - SG_LOG( SG_CLIPPER, SG_INFO, "Loading " << path << ":" << poly_name << "-" << poly_type << " contours = " << contours ); - poly.erase(); for ( i = 0; i < contours; ++i ) { @@ -355,6 +399,8 @@ bool TGConstruct::load_poly(const string& path) { // Once the full poly is loaded, build the clip mask shape.BuildMask(); + shape.id = cur_id++; + polys_in.add_shape( area, shape ); } @@ -481,6 +527,8 @@ int TGConstruct::LoadLandclassPolys( void ) { } simgear::PathList files = d.children(simgear::Dir::TYPE_FILE); + SG_LOG( SG_CLIPPER, SG_INFO, "Loading " << files.size() << " polys from " << d.path() ); + BOOST_FOREACH(const SGPath& p, files) { if (p.file_base() != tile_str) { continue; @@ -1267,17 +1315,6 @@ bool TGConstruct::ClipLandclassPolys( void ) { #endif } -#if 0 - if ( (i == 3) && (j == 137) ) { - SG_LOG( SG_CLIPPER, SG_INFO, "Error Poly\n" << tmp ); - - sprintf( layer_name, "preclip" ); - l_id = tgShapefileOpenLayer( ds_id, layer_name ); - sprintf( feature_name, "preclip" ); - tgShapefileCreateFeature( ds_id, l_id, tmp, feature_name ); - } -#endif - #if USE_CLIPPER clipped = tgPolygonDiffClipper( tmp, accum ); #else @@ -1298,6 +1335,7 @@ bool TGConstruct::ClipLandclassPolys( void ) { // copy all of the superpolys and texparams shape.SetMask( clipped ); shape.textured = polys_in.get_textured( i, j ); + shape.id = polys_in.get_shape( i, j ).id; shape.sps = polys_in.get_shape( i, j ).sps; shape.tps = polys_in.get_shape( i, j ).tps; @@ -1622,33 +1660,24 @@ void TGConstruct::TesselatePolys( void ) // tesselate the polygons and prepair them for final output point_list poly_extra; Point3D min, max; - + for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { + unsigned int id = polys_clipped.get_shape( area, shape ).id; + + if ( IsDebugShape( id ) ) { + WriteDebugShape( "preteselate", area, shape ); + } + for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { TGPolygon poly = polys_clipped.get_poly(area, shape, segment); poly.get_bounding_box(min, max); poly_extra = nodes.get_geod_inside( min, max ); - + SG_LOG( SG_CLIPPER, SG_INFO, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) << ": flag = " << polys_clipped.get_flag(area, shape, segment)); -#if 0 - if ( (i == 3) && (j == 137) ) { - SG_LOG( SG_CLIPPER, SG_INFO, "Error Poly\n" << poly ); - - - sprintf( layer_name, "pretesselate" ); - l_id = tgShapefileOpenLayer( ds_id, layer_name ); - sprintf( feature_name, "pretesselate" ); - tgShapefileCreateFeature( ds_id, l_id, poly, feature_name ); - - // close befoe the crash - tgShapefileCloseDatasource( ds_id ); - } -#endif - TGPolygon tri = polygon_tesselate_alt_with_extra( poly, poly_extra, false ); // ensure all added nodes are accounted for @@ -1849,10 +1878,10 @@ void TGConstruct::CalcTextureCoordinates( void ) TGPolygon tc; if ( polys_clipped.get_textured( area, shape ) ) { - SG_LOG(SG_GENERAL, SG_INFO, "USE TEXTURE PARAMS for tex coord calculations" ); + SG_LOG(SG_GENERAL, SG_DEBUG, "USE TEXTURE PARAMS for tex coord calculations" ); tc = linear_tex_coords( tri, polys_clipped.get_texparams(area, shape, segment) ); } else { - SG_LOG(SG_GENERAL, SG_INFO, "USE SIMGEAR for tex coord calculations" ); + SG_LOG(SG_GENERAL, SG_DEBUG, "USE SIMGEAR for tex coord calculations" ); tc = area_tex_coords( tri ); } polys_clipped.set_texcoords( area, shape, segment, tc ); @@ -1867,14 +1896,14 @@ void TGConstruct::CalcTextureCoordinates( void ) // loading, clipping, tesselating, normals, and output // Also, we are still calculating some thing more than one // (like face area - need to move this into superpoly ) -void TGConstruct::ConstructBucket( SGBucket b ) { +void TGConstruct::ConstructBucket() { - sprintf(ds_name, "./construct_debug_%ld", b.gen_index() ); - ds_id = tgShapefileOpenDatasource( ds_name ); + /* If we have some debug IDs, create a datasource */ + if ( debug_shapes.size() ) { + sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); + } - bucket = b; - - SG_LOG(SG_GENERAL, SG_ALERT, "Construct tile, bucket = " << bucket ); + SG_LOG(SG_GENERAL, SG_ALERT, "Construct tile, bucket = " << bucket << " debug_string: " << ds_name ); // STEP 1) // Load grid of elevation data (Array) diff --git a/src/BuildTiles/Main/construct.hxx b/src/BuildTiles/Main/construct.hxx index 30dd13d1..1c5235a9 100644 --- a/src/BuildTiles/Main/construct.hxx +++ b/src/BuildTiles/Main/construct.hxx @@ -50,6 +50,8 @@ #include "priorities.hxx" +#define USE_CLIPPER (0) + class TGShape { public: @@ -57,6 +59,7 @@ public: bool textured; superpoly_list sps; texparams_list tps; + unsigned int id; void SetMask( TGPolygon mask ) { @@ -71,7 +74,11 @@ public: for (unsigned int i=0; i debug_shapes; + + // OGR encode variables + // For debug: + void* ds_id; // If we are going to build shapefiles + void* l_id; // datasource and layer IDs + char ds_name[128]; + char layer_name[128]; + char feature_name[128]; + // this bucket SGBucket bucket; @@ -263,7 +287,7 @@ private: // SHared Edges match data TGMatch match; - + private: // Load Data void LoadElevationArray( void ); @@ -291,7 +315,7 @@ private: void TesselatePolys( void ); // Elevation and Flattening - void CalcElevations( void ); + void CalcElevations( void ); // Normals and texture coords void LookupNodesPerVertex( void ); @@ -311,14 +335,20 @@ private: void calc_normals( point_list& wgs84_nodes, TGSuperPoly& sp ); double calc_tri_area( int_list& triangle_nodes ); + // debug + bool IsDebugShape( unsigned int id ); + void WriteDebugShape( const char* layer_name, unsigned int area, unsigned int shape ); + public: // Constructor TGConstruct(); // Destructor ~TGConstruct(); + + void set_bucket( SGBucket b ) { bucket = b; } - void ConstructBucket( SGBucket b ); + void ConstructBucket(); void calc_gc_course_dist( const Point3D& start, const Point3D& dest, @@ -369,6 +399,9 @@ public: // normal list (for each point) in cart coords (for smooth // shading) inline point_list get_point_normals() const { return nodes.get_normals(); } + + // Debug + void set_debug( std::string path, std::vector defs ); }; diff --git a/src/BuildTiles/Main/main.cxx b/src/BuildTiles/Main/main.cxx index b3e8b7bf..70eef44e 100644 --- a/src/BuildTiles/Main/main.cxx +++ b/src/BuildTiles/Main/main.cxx @@ -173,6 +173,9 @@ int main(int argc, char **argv) { double ydist = -1; long tile_id = -1; + string debug_dir = "."; + vector debug_defs; + // flag indicating whether UK grid should be used for in-UK // texture coordinate generation bool useUKgrid = false; @@ -229,6 +232,10 @@ int main(int argc, char **argv) { useOwnSharedEdges = true; } else if (arg.find("--ignore-landmass") == 0) { ignoreLandmass = true; + } else if (arg.find("--debug-dir=") == 0) { + debug_dir = arg.substr(12); + } else if (arg.find("--debug-shapes=") == 0) { + debug_defs.push_back( arg.substr(15) ); } else if (arg.find("--") == 0) { usage(argv[0]); } else { @@ -318,8 +325,11 @@ int main(int argc, char **argv) { c->set_use_own_shared_edges( useOwnSharedEdges ); c->set_ignore_landmass( ignoreLandmass ); c->set_nudge( nudge ); + c->set_bucket( b ); - c->ConstructBucket( b ); + c->set_debug( debug_dir, debug_defs ); + + c->ConstructBucket(); delete c; } else { // build all the tiles in an area @@ -343,8 +353,11 @@ int main(int argc, char **argv) { c->set_use_own_shared_edges( useOwnSharedEdges ); c->set_ignore_landmass( ignoreLandmass ); c->set_nudge( nudge ); - - c->ConstructBucket( b_min ); + c->set_bucket( b_min ); + + c->set_debug( debug_dir, debug_defs ); + + c->ConstructBucket(); delete c; } else { SGBucket b_cur; @@ -373,8 +386,11 @@ int main(int argc, char **argv) { c->set_use_own_shared_edges( useOwnSharedEdges ); c->set_ignore_landmass( ignoreLandmass ); c->set_nudge( nudge ); - - c->ConstructBucket( b_cur ); + c->set_bucket( b_cur ); + + c->set_debug( debug_dir, debug_defs ); + + c->ConstructBucket(); delete c; } else { SG_LOG(SG_GENERAL, SG_ALERT, "skipping " << b_cur); @@ -398,8 +414,11 @@ int main(int argc, char **argv) { c->set_use_own_shared_edges( useOwnSharedEdges ); c->set_ignore_landmass( ignoreLandmass ); c->set_nudge( nudge ); + c->set_bucket( b ); - c->ConstructBucket( b ); + c->set_debug( debug_dir, debug_defs ); + + c->ConstructBucket(); delete c; } diff --git a/src/Lib/Geometry/point3d.hxx b/src/Lib/Geometry/point3d.hxx index d5ea9477..e012a127 100644 --- a/src/Lib/Geometry/point3d.hxx +++ b/src/Lib/Geometry/point3d.hxx @@ -441,8 +441,8 @@ inline bool Point3D::HasElevation() const inline bool Point3D::IsWithin( Point3D min, Point3D max ) const { - return ( (min.n[PX] < n[PX]) && (min.n[PY] < n[PY]) && - (max.n[PX] > n[PX]) && (max.n[PY] > n[PY]) ); + return ( (min.n[PX] <= n[PX]) && (min.n[PY] <= n[PY]) && + (max.n[PX] >= n[PX]) && (max.n[PY] >= n[PY]) ); } // FRIENDS diff --git a/src/Lib/Geometry/poly_extra.cxx b/src/Lib/Geometry/poly_extra.cxx index cbdfa81e..7c4f6c5b 100644 --- a/src/Lib/Geometry/poly_extra.cxx +++ b/src/Lib/Geometry/poly_extra.cxx @@ -34,11 +34,9 @@ // Divide segment if there are other existing points on it, return the // new polygon void add_intermediate_nodes( int contour, const Point3D& start, - const Point3D& end, const TGTriNodes& tmp_nodes, + const Point3D& end, point_list& tmp_nodes, TGPolygon *result ) { - point_list nodes = tmp_nodes.get_node_list(); - // SG_LOG(SG_GENERAL, SG_DEBUG, " add_intermediate_nodes()"); char buf[200]; snprintf(buf, 199, " %.7f %.7f %.7f <=> %.7f %.7f %.7f\n", @@ -47,7 +45,7 @@ void add_intermediate_nodes( int contour, const Point3D& start, Point3D new_pt; - bool found_extra = find_intermediate_node( start, end, nodes, &new_pt ); + bool found_extra = find_intermediate_node( start, end, tmp_nodes, &new_pt ); if ( found_extra ) { // recurse with two sub segments @@ -72,9 +70,10 @@ void add_intermediate_nodes( int contour, const Point3D& start, // avoid "T" intersections. TGPolygon add_nodes_to_poly( const TGPolygon& poly, - const TGTriNodes& tmp_nodes ) { + const TGTriNodes& nodes ) { int i, j; TGPolygon result; result.erase(); + point_list tmp_nodes = nodes.get_node_list(); Point3D p0, p1; // SG_LOG(SG_GENERAL, SG_DEBUG, "add_nodes_to_poly"); @@ -114,42 +113,18 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly, return result; } -// Divide segment if there are other existing points on it, return the -// new polygon -void add_intermediate_tgnodes( int contour, const Point3D& start, - const Point3D& end, const TGNodes* nodes, - TGPolygon *result ) -{ - point_list points = nodes->get_geod_nodes(); - - SG_LOG(SG_GENERAL, SG_DEBUG, " add_intermediate_nodes()"); - char buf[200]; - snprintf(buf, 199, " %.7f %.7f %.7f <=> %.7f %.7f %.7f\n", - start.x(), start.y(), start.z(), end.x(), end.y(), end.z() ); - SG_LOG(SG_GENERAL, SG_DEBUG, buf); - - Point3D new_pt; - bool found_extra = find_intermediate_node( start, end, points, &new_pt ); - - if ( found_extra ) { - SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << start << " " << new_pt << " " << end); - add_intermediate_tgnodes( contour, start, new_pt, nodes, result ); - - result->add_node( contour, new_pt ); - SG_LOG(SG_GENERAL, SG_DEBUG, " added = " << new_pt); - - // DEBUG : Was new node shared? - - add_intermediate_tgnodes( contour, new_pt, end, nodes, result ); - } -} - TGPolygon add_tgnodes_to_poly( const TGPolygon& poly, const TGNodes* nodes ) { TGPolygon result; result.erase(); + Point3D min, max; Point3D p0, p1; + point_list poly_points; + + poly.get_bounding_box(min, max); + SG_LOG(SG_GENERAL, SG_DEBUG, "add_tgnodes_to_poly : min " << min << " max " << max ); + + poly_points = nodes->get_geod_inside( min, max ); - SG_LOG(SG_GENERAL, SG_DEBUG, "add_nodes_to_poly"); for ( int i = 0; i < poly.contours(); ++i ) { SG_LOG(SG_GENERAL, SG_DEBUG, "contour = " << i); for ( int j = 0; j < poly.contour_size(i) - 1; ++j ) { @@ -160,7 +135,7 @@ TGPolygon add_tgnodes_to_poly( const TGPolygon& poly, result.add_node( i, p0 ); // add intermediate points - add_intermediate_tgnodes( i, p0, p1, nodes, &result ); + add_intermediate_nodes( i, p0, p1, poly_points, &result ); // end of segment is beginning of next segment } @@ -171,12 +146,11 @@ TGPolygon add_tgnodes_to_poly( const TGPolygon& poly, result.add_node( i, p0 ); // add intermediate points - add_intermediate_tgnodes( i, p0, p1, nodes, &result ); + add_intermediate_nodes( i, p0, p1, poly_points, &result ); // maintain original hole flag setting result.set_hole_flag( i, poly.get_hole_flag( i ) ); } return result; -} - +} \ No newline at end of file diff --git a/src/Lib/Geometry/poly_support.cxx b/src/Lib/Geometry/poly_support.cxx index e49cca7a..42e7a706 100644 --- a/src/Lib/Geometry/poly_support.cxx +++ b/src/Lib/Geometry/poly_support.cxx @@ -991,8 +991,8 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end, // cout << i << endl; Point3D current = nodes[i]; - if ( (current.x() > (p_min.x() + SG_EPSILON)) - && (current.x() < (p_max.x() - SG_EPSILON)) ) { + if ( (current.x() > (p_min.x() + (SG_EPSILON))) + && (current.x() < (p_max.x() - (SG_EPSILON))) ) { // printf( "found a potential candidate %.7f %.7f %.7f\n", // current.x(), current.y(), current.z() ); @@ -1039,8 +1039,8 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end, for ( int i = 0; i < (int)nodes.size(); ++i ) { Point3D current = nodes[i]; - if ( (current.y() > (p_min.y() + SG_EPSILON)) - && (current.y() < (p_max.y() - SG_EPSILON)) ) { + if ( (current.y() > (p_min.y() + (SG_EPSILON))) + && (current.y() < (p_max.y() - (SG_EPSILON))) ) { // printf( "found a potential candidate %.7f %.7f %.7f\n", // current.x(), current.y(), current.z() ); @@ -1507,10 +1507,15 @@ void* tgShapefileOpenDatasource( const char* datasource_name ) SG_LOG(SG_GENERAL, SG_ALERT, "Unknown datasource format driver: " << format_name); exit(1); } - - datasource = ogrdriver->CreateDataSource(datasource_name, NULL); + + datasource = ogrdriver->Open(datasource_name, TRUE); + if (!datasource) { - SG_LOG(SG_GENERAL, SG_ALERT, "Unable to create datasource: " << datasource_name); + datasource = ogrdriver->CreateDataSource(datasource_name, NULL); + } + + if (!datasource) { + SG_LOG(SG_GENERAL, SG_ALERT, "Unable to open or create datasource: " << datasource_name); exit(1); } @@ -1523,19 +1528,25 @@ void* tgShapefileOpenLayer( void* ds_id, const char* layer_name ) { OGRSpatialReference srs; srs.SetWellKnownGeogCS("WGS84"); - layer = datasource->CreateLayer( layer_name, &srs, wkbPolygon25D, NULL); + + layer = datasource->GetLayerByName(layer_name); + + if (!layer) { + layer = datasource->CreateLayer( layer_name, &srs, wkbPolygon25D, NULL); + + OGRFieldDefn descriptionField("ID", OFTString); + descriptionField.SetWidth(128); + + if( layer->CreateField( &descriptionField ) != OGRERR_NONE ) { + SG_LOG(SG_GENERAL, SG_ALERT, "Creation of field 'Description' failed"); + } + } + if (!layer) { SG_LOG(SG_GENERAL, SG_ALERT, "Creation of layer '" << layer_name << "' failed"); return NULL; } - - OGRFieldDefn descriptionField("ID", OFTString); - descriptionField.SetWidth(128); - - if( layer->CreateField( &descriptionField ) != OGRERR_NONE ) { - SG_LOG(SG_GENERAL, SG_ALERT, "Creation of field 'Description' failed"); - } - + return (void*)layer; } @@ -1588,10 +1599,11 @@ void tgShapefileCloseLayer( void* l_id ) //OGRLayer::DestroyLayer( layer ); } -void tgShapefileCloseDatasource( void* ds_id ) +void* tgShapefileCloseDatasource( void* ds_id ) { OGRDataSource* datasource = (OGRDataSource *)ds_id; OGRDataSource::DestroyDataSource( datasource ); -} + return (void *)-1; +} \ No newline at end of file diff --git a/src/Lib/Geometry/poly_support.hxx b/src/Lib/Geometry/poly_support.hxx index 58b8918d..d263de1a 100644 --- a/src/Lib/Geometry/poly_support.hxx +++ b/src/Lib/Geometry/poly_support.hxx @@ -116,7 +116,7 @@ void* tgShapefileOpenDatasource( const char* datasource_name ); void* tgShapefileOpenLayer( void* ds_id, const char* layer_name ); void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* feature_name ); void tgShapefileCloseLayer( void* l_id ); -void tgShapefileCloseDatasource( void* ds_id ); +void* tgShapefileCloseDatasource( void* ds_id ); #endif // _POLY_SUPPORT_HXX diff --git a/src/Lib/Geometry/tg_nodes.cxx b/src/Lib/Geometry/tg_nodes.cxx index eb7309be..6553c781 100644 --- a/src/Lib/Geometry/tg_nodes.cxx +++ b/src/Lib/Geometry/tg_nodes.cxx @@ -106,9 +106,13 @@ point_list TGNodes::get_geod_inside( Point3D min, Point3D max ) const { for ( ; current != last; ++current ) { Point3D pt = (*current).GetPosition(); - + if ( pt.IsWithin( min, max ) ) { points.push_back( pt ); + } else { + if ( (pt < max) && (pt > min) ) { + SG_LOG(SG_GENERAL, SG_ALERT, "pt " << pt << " failes IsWithin, but sholdn't have: min " << min << " max " << max ); + } } } diff --git a/src/Lib/Polygon/clipper.cpp b/src/Lib/Polygon/clipper.cpp index d7071269..bc0aa9e2 100644 --- a/src/Lib/Polygon/clipper.cpp +++ b/src/Lib/Polygon/clipper.cpp @@ -1,8 +1,8 @@ /******************************************************************************* * * * Author : Angus Johnson * -* Version : 4.8.5 * -* Date : 15 July 2012 * +* Version : 4.8.3 * +* Date : 27 May 2012 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2012 * * * @@ -61,7 +61,7 @@ enum Direction { dRightToLeft, dLeftToRight }; inline long64 Abs(long64 val) { - return val < 0 ? -val : val; + if (val < 0) return -val; else return val; } //------------------------------------------------------------------------------ @@ -1221,7 +1221,7 @@ bool PolySort(OutRec *or1, OutRec *or2) { if (or1->pts != or2->pts) { - return or1->pts ? true : false; + if (or1->pts) return true; else return false; } else return false; } @@ -1235,7 +1235,8 @@ bool PolySort(OutRec *or1, OutRec *or2) int result = i1 - i2; if (result == 0 && (or1->isHole != or2->isHole)) { - return or1->isHole ? false : true; + if (or1->isHole) return false; + else return true; } else return result < 0; } @@ -1578,10 +1579,8 @@ 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(e2, e1); + else + AppendPolygon( e1, e2 ); } //------------------------------------------------------------------------------ @@ -2098,8 +2097,7 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt) op->next = op; op->prev = op; SetHoleState(e, outRec); - } - else + } else { OutRec *outRec = m_PolyOuts[e->outIdx]; OutPt* op = outRec->pts; @@ -2110,17 +2108,12 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt) { //check for 'rounding' artefacts ... if (outRec->sides == esNeither && pt.Y == op->pt.Y) - { if (ToFront) { if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt } - else - { - if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt - } - } - + else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt + outRec->sides = (EdgeSide)(outRec->sides | e->side); if (outRec->sides == esBoth) { @@ -2317,7 +2310,8 @@ void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) TEdge* GetNextInAEL(TEdge *e, Direction dir) { - return dir == dLeftToRight ? e->nextInAEL : e->prevInAEL; + if( dir == dLeftToRight ) return e->nextInAEL; + else return e->prevInAEL; } //------------------------------------------------------------------------------ @@ -2534,12 +2528,12 @@ bool Process1Before2(IntersectNode &node1, IntersectNode &node2) if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) { result = node2.pt.X > node1.pt.X; - return node2.edge1->dx > 0 ? !result : result; + if (node2.edge1->dx > 0) return !result; else return result; } else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) { result = node2.pt.X > node1.pt.X; - return node2.edge2->dx > 0 ? !result : result; + if (node2.edge2->dx > 0) return !result; else return result; } else return node2.pt.X > node1.pt.X; } @@ -2865,7 +2859,8 @@ bool Clipper::FixupIntersections() bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) { - return e2.xcurr == e1.xcurr ? e2.dx > e1.dx : e2.xcurr < e1.xcurr; + if (e2.xcurr == e1.xcurr) return e2.dx > e1.dx; + else return e2.xcurr < e1.xcurr; } //------------------------------------------------------------------------------ @@ -3131,13 +3126,12 @@ struct DoublePoint Polygon BuildArc(const IntPoint &pt, const double a1, const double a2, const double r) { - 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); + 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; 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); @@ -3290,18 +3284,19 @@ void DoSquare(double mul = 1.0) (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - double sinAngle = normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y; - if (sinAngle * m_delta >= 0) + if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) { - //occasionally (due to floating point math) sinAngle can be > 1 so ... - if (sinAngle > 1) sinAngle = 1; else if (sinAngle < -1) sinAngle = -1; - double dx = tan((pi - asin(sinAngle))/4) * abs(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 { diff --git a/src/Lib/Polygon/clipper.hpp b/src/Lib/Polygon/clipper.hpp index 26ad6281..35ec6c97 100644 --- a/src/Lib/Polygon/clipper.hpp +++ b/src/Lib/Polygon/clipper.hpp @@ -1,8 +1,8 @@ /******************************************************************************* * * * Author : Angus Johnson * -* Version : 4.8.5 * -* Date : 15 July 2012 * +* Version : 4.8.3 * +* Date : 27 May 2012 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2012 * * * diff --git a/src/Lib/Polygon/polygon.cxx b/src/Lib/Polygon/polygon.cxx index 89e8f3ab..d78534ff 100644 --- a/src/Lib/Polygon/polygon.cxx +++ b/src/Lib/Polygon/polygon.cxx @@ -51,6 +51,27 @@ TGPolygon::TGPolygon( void ) TGPolygon::~TGPolygon( void ) { } +void TGPolygon::get_bounding_box( Point3D& min, Point3D& max ) const +{ + double minx = std::numeric_limits::infinity(); + double miny = std::numeric_limits::infinity(); + double maxx = -std::numeric_limits::infinity(); + double maxy = -std::numeric_limits::infinity(); + + for ( int i = 0; i < contours(); i++ ) { + for (unsigned int j = 0; j < poly[i].size(); j++) { + Point3D pt = poly[i][j]; + if ( pt.x() < minx ) { minx = pt.x(); } + if ( pt.x() > maxx ) { maxx = pt.x(); } + if ( pt.y() < miny ) { miny = pt.y(); } + if ( pt.y() > maxy ) { maxy = pt.y(); } + } + } + + min = Point3D( minx, miny, 0.0 ); + max = Point3D( maxx, maxy, 0.0 ); +} + // Set the elevations of points in the current polgyon based on the // elevations of points in source. For points that are not found in diff --git a/src/Lib/Polygon/polygon.hxx b/src/Lib/Polygon/polygon.hxx index 417d69ee..fb93c790 100644 --- a/src/Lib/Polygon/polygon.hxx +++ b/src/Lib/Polygon/polygon.hxx @@ -153,19 +153,7 @@ inline void set_pt( int contour, int i, const Point3D& p ) poly[contour][i] = p; } -inline void get_bounding_box( Point3D& min, Point3D& max ) -{ - min = Point3D( std::numeric_limits::infinity(), std::numeric_limits::infinity(), 0.0 ); - max = Point3D( -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), 0.0 ); - - for ( int i = 0; i < contours(); i++ ) { - for (unsigned int j = 0; j < poly[i].size(); j++) { - Point3D pt = poly[i][j]; - if ( pt < min ) { min = pt; } - if ( pt > max ) { max = pt; } - } - } -} +void get_bounding_box( Point3D& min, Point3D& max ) const; // get and set an arbitrary point inside the specified polygon contour inline Point3D get_point_inside( const int contour ) const