diff --git a/src/BuildTiles/Main/construct.cxx b/src/BuildTiles/Main/construct.cxx index c151eeec..ff2c17ce 100644 --- a/src/BuildTiles/Main/construct.cxx +++ b/src/BuildTiles/Main/construct.cxx @@ -72,6 +72,7 @@ TGConstruct::TGConstruct(): useUKGrid(false), writeSharedEdges(true), useOwnSharedEdges(false), + debug_all(false), ds_id((void*)-1) { } @@ -102,17 +103,22 @@ void TGConstruct::set_debug( std::string path, std::vector defs ) 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); + if ( dsd == "all" ) { + debug_all = true; + } else { + std::stringstream ss(dsd); + int i; - debug_shapes.push_back(i); + while (ss >> i) + { + SG_LOG(SG_GENERAL, SG_ALERT, "Adding debug file " << i); - if (ss.peek() == ',') - ss.ignore(); + debug_shapes.push_back(i); + + if (ss.peek() == ',') + ss.ignore(); + } } } } @@ -122,26 +128,56 @@ bool TGConstruct::IsDebugShape( unsigned int id ) { bool is_debug = false; - for (unsigned int i=0; i 0 ) { + +#if FIND_SLIVERS // move slivers from clipped polygon to slivers polygon tgPolygonFindSlivers( clipped, slivers ); +#endif // add the sliverless result polygon to the clipped polys list if ( clipped.contours() > 0 ) { TGShape shape; TGSuperPoly sp; - sp.set_material( get_area_name( (AreaType)i ) ); + //sp.set_material( get_area_name( (AreaType)i ) ); // copy all of the superpolys and texparams shape.SetMask( clipped ); @@ -1339,47 +1424,81 @@ bool TGConstruct::ClipLandclassPolys( void ) { shape.sps = polys_in.get_shape( i, j ).sps; shape.tps = polys_in.get_shape( i, j ).tps; - shape.sps.push_back( sp ); + // shape.sps.push_back( sp ); polys_clipped.add_shape( i, shape ); + + if ( IsDebugShape( shape.id ) ) { + WriteDebugShape( "clipped", shape ); + } } } #if USE_CLIPPER accum = tgPolygonUnionClipper( tmp, accum ); +// accum = tgPolygonUnionClipper( clipped, accum ); +#else + +#if USE_ACCUMULATOR + tgPolygonAddToAccumulator( tmp ); +// tgPolygonAddToAccumulator( clipped ); #else accum = tgPolygonUnion( tmp, accum ); +// accum = tgPolygonUnion( clipped, accum ); +#endif + #endif } } + if ( debug_all || debug_shapes.size() ) { + // Dump the sliver list + WriteDebugPolys( "poly_slivers", slivers ); + } + +#if FIND_SLIVERS // Now, merge any slivers with clipped polys merge_slivers(polys_clipped, slivers); +#endif + slivers.clear(); + // finally, what ever is left over goes to ocean - - // clip to accum against original base tile - // remains = new gpc_polygon; - // remains->num_contours = 0; - // remains->contour = NULL; #if USE_CLIPPER remains = tgPolygonDiffClipper( safety_base, accum ); #else + +#if USE_ACCUMULATOR + remains = tgPolygonDiffWithAccumulator( safety_base ); +#else remains = tgPolygonDiff( safety_base, accum ); +#endif + #endif if ( remains.contours() > 0 ) { // cout << "remains contours = " << remains.contours() << endl; // move slivers from remains polygon to slivers polygon + +#if FIND_SLIVERS tgPolygonFindSlivers( remains, slivers ); +#endif // cout << " After sliver move:" << endl; // cout << " remains = " << remains.contours() << endl; // cout << " slivers = " << slivers.contours() << endl; +#if FIND_SLIVERS // merge any slivers with previously clipped // neighboring polygons if ( slivers.size() > 0 ) { + + if ( debug_all || debug_shapes.size() ) { + // Dump the sliver list + WriteDebugPolys( "remains_slivers", slivers ); + } + merge_slivers(polys_clipped, slivers); } +#endif if ( remains.contours() > 0 ) { TGSuperPoly sp; @@ -1396,6 +1515,10 @@ bool TGConstruct::ClipLandclassPolys( void ) { } } +#if USE_ACCUMULATOR + tgPolygonFreeAccumulator(); +#endif + // Once clipping is complete, intersect the individual segments with their clip masks for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { @@ -1664,9 +1787,9 @@ void TGConstruct::TesselatePolys( void ) 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 ); + WriteDebugShape( "preteselate", polys_clipped.get_shape(area, shape) ); } for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { @@ -1834,16 +1957,20 @@ void TGConstruct::WriteBtgFile( void ) } } -void TGConstruct::clean_clipped_polys() { +void TGConstruct::CleanClippedPolys() { // Clean the polys + unsigned int before, after; + 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; + for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { TGPolygon poly = polys_clipped.get_poly(area, shape, segment); - SG_LOG( SG_CLIPPER, SG_INFO, "Cleaning poly " << get_area_name( (AreaType)area ) << - ":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) ); - if ( area == 3 ) { + before = poly.total_size(); + + if ( false ) { poly = remove_cycles( poly ); poly = remove_dups( poly ); poly = remove_bad_contours( poly ); @@ -1859,8 +1986,19 @@ void TGConstruct::clean_clipped_polys() { poly = remove_bad_contours( poly ); } + after = poly.total_size(); + + if (before != after) { + SG_LOG( SG_CLIPPER, SG_INFO, "Cleanined poly " << get_area_name( (AreaType)area ) << + ":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) << " before: " << before << " after: " << after ); + } + polys_clipped.set_poly( area, shape, segment, poly ); } + + if ( IsDebugShape( id ) ) { + WriteDebugShape( "cleaned", polys_clipped.get_shape( area, shape ) ); + } } } } @@ -1899,7 +2037,7 @@ void TGConstruct::CalcTextureCoordinates( void ) void TGConstruct::ConstructBucket() { /* If we have some debug IDs, create a datasource */ - if ( debug_shapes.size() ) { + if ( debug_shapes.size() || debug_all ) { sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); } @@ -1927,6 +2065,11 @@ void TGConstruct::ConstructBucket() { // Clip the Landclass polygons ClipLandclassPolys(); + // STEP 5) + // Clean the polys - after this, we shouldn't change their shape (other than slightly for + // fix T-Junctions - as This is the end of the first pass for multicore design + CleanClippedPolys(); + // STEP 5) // Merge in Shared data (just add the nodes to the nodelist) // When this step is complete, some nodes will have normals (from shared tiles) @@ -1941,7 +2084,7 @@ void TGConstruct::ConstructBucket() { // TODO : Needs to be part of clipping // just before union : If we need to clean again after fixing tjunctions, make // sure we don't alter the shape - clean_clipped_polys(); + // CleanClippedPolys(); // STEP 7) // Generate triangles - we can't generate the node-face lookup table diff --git a/src/BuildTiles/Main/construct.hxx b/src/BuildTiles/Main/construct.hxx index 1c5235a9..d909bb33 100644 --- a/src/BuildTiles/Main/construct.hxx +++ b/src/BuildTiles/Main/construct.hxx @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -51,6 +52,8 @@ #include "priorities.hxx" #define USE_CLIPPER (0) +#define FIND_SLIVERS (1) +#define USE_ACCUMULATOR (1) class TGShape { @@ -59,8 +62,14 @@ public: bool textured; superpoly_list sps; texparams_list tps; + AreaType area; unsigned int id; + void GetName( char* name ) const + { + sprintf( name, "%s_%d", get_area_name( (AreaType)area ).c_str(), id ); + } + void SetMask( TGPolygon mask ) { clip_mask = mask; @@ -84,17 +93,23 @@ public: void IntersectPolys( void ) { - TGPolygon original, intersect; + if ( sps.size() > 1 ) { + TGPolygon original, intersect; + + for (unsigned int i=0; i debug_shapes; @@ -308,8 +325,8 @@ private: void SaveSharedEdgeData( void ); // Polygon Cleaning + void CleanClippedPolys( void ); void FixTJunctions( void ); - void clean_clipped_polys( void ); // Tesselation void TesselatePolys( void ); @@ -337,8 +354,10 @@ private: // debug bool IsDebugShape( unsigned int id ); - void WriteDebugShape( const char* layer_name, unsigned int area, unsigned int shape ); - + 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 ); + public: // Constructor TGConstruct(); diff --git a/src/BuildTiles/Match/match.cxx b/src/BuildTiles/Match/match.cxx index ff1d5381..51ca6893 100644 --- a/src/BuildTiles/Match/match.cxx +++ b/src/BuildTiles/Match/match.cxx @@ -273,9 +273,6 @@ void TGMatch::load_neighbor_shared( SGBucket b, string work ) { // try to load any missing shared data from our own shared data file void TGMatch::load_missing_shared( SGBucket b, string work ) { - double clon = b.get_center_lon(); - double clat = b.get_center_lat(); - string base = work + "/Shared/"; if ( !nw_flag ) { diff --git a/src/Lib/Geometry/point3d.hxx b/src/Lib/Geometry/point3d.hxx index e012a127..fd606f2f 100644 --- a/src/Lib/Geometry/point3d.hxx +++ b/src/Lib/Geometry/point3d.hxx @@ -142,6 +142,7 @@ public: bool HasElevation() const; // does point have elevation data? bool IsWithin( Point3D min, Point3D max ) const; + bool IsWithin( double xmin, double xmax, double ymin, double ymax ) const; #ifdef _MSC_VER double round(double d) @@ -445,6 +446,12 @@ inline bool Point3D::IsWithin( Point3D min, Point3D max ) const (max.n[PX] >= n[PX]) && (max.n[PY] >= n[PY]) ); } +inline bool Point3D::IsWithin( double xmin, double xmax, double ymin, double ymax ) const +{ + return ( (xmin <= n[PX]) && (ymin <= n[PY]) && + (xmax >= n[PX]) && (ymax >= n[PY]) ); +} + // FRIENDS inline Point3D operator - (const Point3D& a) diff --git a/src/Lib/Geometry/poly_extra.cxx b/src/Lib/Geometry/poly_extra.cxx index 7c4f6c5b..26cafa92 100644 --- a/src/Lib/Geometry/poly_extra.cxx +++ b/src/Lib/Geometry/poly_extra.cxx @@ -34,33 +34,28 @@ // 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, point_list& tmp_nodes, - TGPolygon *result ) + const Point3D& end, point_list& tmp_nodes, + TGPolygon *result, + const double bbEpsilon, + const double errEpsilon + ) { - // 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_BULK, buf); - - Point3D new_pt; - bool found_extra = find_intermediate_node( start, end, tmp_nodes, &new_pt ); + + SG_LOG(SG_GENERAL, SG_BULK, " " << start << " <==> " << end ); + + bool found_extra = find_intermediate_node( start, end, tmp_nodes, &new_pt, bbEpsilon, errEpsilon ); if ( found_extra ) { - // recurse with two sub segments - // SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << p0 << " " << nodes[extra_index] - // << " " << p1); - add_intermediate_nodes( contour, start, new_pt, tmp_nodes, - result ); + // recurse with two sub segments + // SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << p0 << " " << nodes[extra_index] + // << " " << p1); + add_intermediate_nodes( contour, start, new_pt, tmp_nodes, result, bbEpsilon, errEpsilon ); - result->add_node( contour, new_pt ); + result->add_node( contour, new_pt ); SG_LOG(SG_GENERAL, SG_BULK, " adding = " << new_pt); - add_intermediate_nodes( contour, new_pt, end, tmp_nodes, - result ); - } else { - // this segment does not need to be divided + add_intermediate_nodes( contour, new_pt, end, tmp_nodes, result, bbEpsilon, errEpsilon ); } } @@ -88,7 +83,7 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly, result.add_node( i, p0 ); // add intermediate points - add_intermediate_nodes( i, p0, p1, tmp_nodes, &result ); + add_intermediate_nodes( i, p0, p1, tmp_nodes, &result, SG_EPSILON*10, SG_EPSILON*4 ); // end of segment is beginning of next segment } @@ -99,7 +94,7 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly, result.add_node( i, p0 ); // add intermediate points - add_intermediate_nodes( i, p0, p1, tmp_nodes, &result ); + add_intermediate_nodes( i, p0, p1, tmp_nodes, &result, SG_EPSILON*10, SG_EPSILON*4 ); // end of segment is beginning of next segment // 5/9/2000 CLO - this results in duplicating the last point @@ -135,7 +130,7 @@ TGPolygon add_tgnodes_to_poly( const TGPolygon& poly, result.add_node( i, p0 ); // add intermediate points - add_intermediate_nodes( i, p0, p1, poly_points, &result ); + add_intermediate_nodes( i, p0, p1, poly_points, &result, SG_EPSILON*10, SG_EPSILON*4 ); // end of segment is beginning of next segment } @@ -146,7 +141,7 @@ TGPolygon add_tgnodes_to_poly( const TGPolygon& poly, result.add_node( i, p0 ); // add intermediate points - add_intermediate_nodes( i, p0, p1, poly_points, &result ); + add_intermediate_nodes( i, p0, p1, poly_points, &result, SG_EPSILON*10, SG_EPSILON*4 ); // maintain original hole flag setting result.set_hole_flag( i, poly.get_hole_flag( i ) ); diff --git a/src/Lib/Geometry/poly_extra.hxx b/src/Lib/Geometry/poly_extra.hxx index 78e72a7e..580151de 100644 --- a/src/Lib/Geometry/poly_extra.hxx +++ b/src/Lib/Geometry/poly_extra.hxx @@ -37,8 +37,11 @@ // 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, - TGPolygon *result ); + const Point3D& end, const point_list& tmp_nodes, + TGPolygon *result, + const double bbEpsilon = SG_EPSILON*10, + const double errEpsilon = SG_EPSILON*4 + ); // Search each segment for additional vertex points that may have been diff --git a/src/Lib/Geometry/poly_support.cxx b/src/Lib/Geometry/poly_support.cxx index 42e7a706..f1d0a5d2 100644 --- a/src/Lib/Geometry/poly_support.cxx +++ b/src/Lib/Geometry/poly_support.cxx @@ -946,14 +946,16 @@ TGPolygon snap (const TGPolygon &poly, double grid_size) } -// static const double tgAirportEpsilon = SG_EPSILON / 10.0; -static const double tgAirportEpsilon = SG_EPSILON; - +/* TODO : Verify this doesn't break genapt850 - may need an interface to + * specify bounding box and error values + */ // Find a point in the given node list that lies between start and // end, return true if something found, false if nothing found. bool find_intermediate_node( const Point3D& start, const Point3D& end, - const point_list& nodes, Point3D *result ) + const point_list& nodes, Point3D *result, + double bbEpsilon, double errEpsilon + ) { bool found_node = false; double m, m1, b, b1, y_err, x_err, y_err_min, x_err_min; @@ -991,8 +993,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() + (bbEpsilon))) + && (current.x() < (p_max.x() - (bbEpsilon))) ) { // printf( "found a potential candidate %.7f %.7f %.7f\n", // current.x(), current.y(), current.z() ); @@ -1000,7 +1002,7 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end, y_err = fabs(current.y() - (m * current.x() + b)); // cout << "y_err = " << y_err << endl; - if ( y_err < tgAirportEpsilon ) { + if ( y_err < errEpsilon ) { // cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl; // cout << p_min << " < " << current << " < " // << p_max << endl; @@ -1039,8 +1041,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() + (bbEpsilon))) + && (current.y() < (p_max.y() - (bbEpsilon))) ) { // printf( "found a potential candidate %.7f %.7f %.7f\n", // current.x(), current.y(), current.z() ); @@ -1052,7 +1054,7 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end, // cout << " (" << counter << ") x_err = " << x_err << endl; // } - if ( x_err < tgAirportEpsilon ) { + if ( x_err < errEpsilon ) { // cout << "FOUND EXTRA SEGMENT NODE (X)" << endl; // cout << p_min << " < " << current << " < " // << p_max << endl; @@ -1550,11 +1552,11 @@ void* tgShapefileOpenLayer( void* ds_id, const char* layer_name ) { return (void*)layer; } -void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* description ) +void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* description, bool has_pt_inside ) { OGRLayer* layer = (OGRLayer*)l_id; OGRPolygon* polygon = new OGRPolygon(); - + for ( int i = 0; i < poly.contours(); i++ ) { bool skip_ring=false; point_list contour = poly.get_contour( i ); @@ -1591,6 +1593,26 @@ void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, c SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create feature in shapefile"); } OGRFeature::DestroyFeature(feature); + + // TEST TEST TEST : Add the point inside - see if we can see it in QGIS + if ( has_pt_inside ) { + OGRPoint *point=new OGRPoint(); + + point->setX( poly.get_point_inside( i ).x() ); + point->setY( poly.get_point_inside( i ).y() ); + point->setZ( 0.0 ); + + SG_LOG(SG_GENERAL, SG_ALERT, "DEBUG: SET POINT INSIDE " << description << " contour " << i << " is " << poly.get_point_inside( i ) ); + + feature = new OGRFeature( layer->GetLayerDefn() ); + feature->SetField("ID", description); + feature->SetGeometry(point); + if( layer->CreateFeature( feature ) != OGRERR_NONE ) + { + SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create feature in shapefile"); + } + OGRFeature::DestroyFeature(feature); + } } } diff --git a/src/Lib/Geometry/poly_support.hxx b/src/Lib/Geometry/poly_support.hxx index d263de1a..2cd9a52d 100644 --- a/src/Lib/Geometry/poly_support.hxx +++ b/src/Lib/Geometry/poly_support.hxx @@ -100,7 +100,10 @@ TGPolygon remove_spikes( const TGPolygon& poly ); // Find a point in the given node list that lies between start and // end, return true if something found, false if nothing found. bool find_intermediate_node( const Point3D& start, const Point3D& end, - const point_list& nodes, Point3D *result ); + const point_list& nodes, Point3D *result, + const double bbEpsilon = SG_EPSILON*10, + const double errEpsilon = SG_EPSILON*4 + ); // remove any degenerate contours TGPolygon remove_bad_contours( const TGPolygon &poly ); @@ -114,7 +117,7 @@ TGPolygon remove_small_contours( const TGPolygon &poly ); void tgShapefileInit( void ); 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 tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* feature_name, bool has_point_inside = false ); void tgShapefileCloseLayer( void* l_id ); void* tgShapefileCloseDatasource( void* ds_id ); diff --git a/src/Lib/Polygon/polygon.cxx b/src/Lib/Polygon/polygon.cxx index d78534ff..09ae45c7 100644 --- a/src/Lib/Polygon/polygon.cxx +++ b/src/Lib/Polygon/polygon.cxx @@ -359,6 +359,8 @@ void tgPolygonFindSlivers( TGPolygon& in, poly_list& slivers ) in.delete_contour( i ); } else { // move sliver contour to out polygon + SG_LOG(SG_GENERAL, SG_INFO, " Found SLIVER!"); + contour = in.get_contour( i ); in.delete_contour( i ); out.add_contour( contour, hole_flag ); @@ -703,6 +705,80 @@ TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const return result; } + +// Accumulator optimization ( to keep from massive data copies and format changes +gpc_polygon *gpc_accumulator = NULL; + +void tgPolygonInitAccumulator( void ) +{ + gpc_accumulator = new gpc_polygon; + gpc_accumulator->num_contours = 0; + gpc_accumulator->contour = NULL; + gpc_accumulator->hole = NULL; +} + +void tgPolygonFreeAccumulator( void ) +{ + gpc_free_polygon( gpc_accumulator ); + delete gpc_accumulator; + gpc_accumulator = NULL; +} + +void tgPolygonAddToAccumulator( const TGPolygon& subject ) +{ + gpc_polygon *gpc_subject = new gpc_polygon; + gpc_subject->num_contours = 0; + gpc_subject->contour = NULL; + gpc_subject->hole = NULL; + make_gpc_poly( subject, gpc_subject ); + + gpc_polygon *gpc_result = new gpc_polygon; + gpc_result->num_contours = 0; + gpc_result->contour = NULL; + gpc_result->hole = NULL; + + gpc_polygon_clip( GPC_UNION, gpc_subject, gpc_accumulator, gpc_result ); + + // free allocated memory + gpc_free_polygon( gpc_subject ); + delete gpc_subject; + + // throw away old accumulator : and use result for now on + gpc_free_polygon( gpc_accumulator ); + delete gpc_accumulator; + gpc_accumulator = gpc_result; +} + +TGPolygon tgPolygonDiffWithAccumulator( const TGPolygon& subject ) +{ + TGPolygon result; + + gpc_polygon *gpc_subject = new gpc_polygon; + gpc_subject->num_contours = 0; + gpc_subject->contour = NULL; + gpc_subject->hole = NULL; + make_gpc_poly( subject, gpc_subject ); + + gpc_polygon *gpc_result = new gpc_polygon; + gpc_result->num_contours = 0; + gpc_result->contour = NULL; + gpc_result->hole = NULL; + + gpc_polygon_clip( GPC_DIFF, gpc_subject, gpc_accumulator, gpc_result ); + make_tg_poly( gpc_result, &result ); + + // free allocated memory + gpc_free_polygon( gpc_subject ); + delete gpc_subject; + + gpc_free_polygon( gpc_result ); + delete gpc_result; + + return result; +} + + + // Difference TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) { return polygon_clip( POLY_DIFF, subject, clip ); diff --git a/src/Lib/Polygon/polygon.hxx b/src/Lib/Polygon/polygon.hxx index fb93c790..8fa454f5 100644 --- a/src/Lib/Polygon/polygon.hxx +++ b/src/Lib/Polygon/polygon.hxx @@ -256,6 +256,12 @@ void tgPolygonFindSlivers( TGPolygon& in, poly_list& slivers ); // wrapper functions for gpc polygon clip routines +void tgPolygonInitAccumulator( void ); +void tgPolygonFreeAccumulator( void ); +void tgPolygonAddToAccumulator( const TGPolygon& subject ); +TGPolygon tgPolygonDiffWithAccumulator( const TGPolygon& subject ); + + // Difference TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip );