diff --git a/src/BuildTiles/Main/default_priorities.txt b/src/BuildTiles/Main/default_priorities.txt index 65142186..779098c6 100644 --- a/src/BuildTiles/Main/default_priorities.txt +++ b/src/BuildTiles/Main/default_priorities.txt @@ -30,7 +30,7 @@ River stream IntermittentStream stream Watercourse stream Canal stream -Cliff cliff # A cliff face +Cliffs cliff # A cliff face Glacier other # Solid ice/snow PackIce other # Water with ice packs PolarIce other @@ -86,7 +86,9 @@ ShrubGrassCover other # Mixed Shrubland/Grassland SavannaCover other # Savanna Orchard other # Orchard DeciduousForest other # Deciduous Forest +DeciduousBroadCover other # Deciduous Forest EvergreenForest other # Evergreen Forest +EvergreenBroadCover other # Evergreen Forest MixedForest other # Mixed Forest RainForest other # Rain Forest BarrenCover other # Barren or Sparsely Vegetated diff --git a/src/BuildTiles/Main/tgconstruct_poly.cxx b/src/BuildTiles/Main/tgconstruct_poly.cxx index 90d52634..5ebec27a 100644 --- a/src/BuildTiles/Main/tgconstruct_poly.cxx +++ b/src/BuildTiles/Main/tgconstruct_poly.cxx @@ -67,8 +67,10 @@ int TGConstruct::LoadLandclassPolys( void ) { } string lext = p.complete_lower_extension(); + string lastext = p.extension(); if ((lext == "arr") || (lext == "arr.gz") || (lext == "btg.gz") || - (lext == "fit") || (lext == "fit.gz") || (lext == "ind")) + (lext == "fit") || (lext == "fit.gz") || (lext == "ind") || + (lastext == "cliffs")) { // skipped! } else { diff --git a/src/Lib/Array/array.cxx b/src/Lib/Array/array.cxx index faf35fef..5138beb8 100644 --- a/src/Lib/Array/array.cxx +++ b/src/Lib/Array/array.cxx @@ -24,6 +24,7 @@ #endif #include +#include //for setprecision #include #include @@ -120,12 +121,8 @@ bool TGArray::load_cliffs(const string & height_base) continue; } - string lext = p.complete_lower_extension(); - if ((lext == "arr") || (lext == "arr.gz") || (lext == "btg.gz") || - (lext == "fit") || (lext == "fit.gz") || (lext == "ind")) - { - // skipped! - } else { + string lext = p.lower_extension(); + if (lext == "cliffs") { gzFile fp = gzopen( p.c_str(), "rb" ); unsigned int count; sgReadUInt( fp, &count ); @@ -572,7 +569,8 @@ double TGArray::altitude_from_grid( double lon, double lat ) const { elev = get_array_elev(corners[0][0],corners[0][1]); break; case 0: // all points on wrong side, fall through to normal calc - SG_LOG(SG_GENERAL, SG_WARN, "All elevation grid points on wrong side of cliff for " << londeg << "," << latdeg ); + SG_LOG(SG_GENERAL, SG_WARN, "All elevation grid points on wrong side of cliff for " << std::setprecision(10) << londeg << "," << latdeg ); + SG_LOG(SG_GENERAL, SG_WARN, "Grid points ("<< std::setprecision(9) << lon1 << "," << lat1 << "),("< 0 ) { if ( subject.GetPreserve3D() ) { result.InheritElevations( subject ); @@ -63,7 +62,8 @@ void tgChopper::ClipRow( const tgPolygon& subject, const double& center_lat, con } } -void tgChopper::Add( const tgPolygon& subject, const std::string& type ) + +void tgChopper::Add( const tgPolygon& subject, const std::string& type) { // bail out immediately if polygon is empty if ( subject.Contours() == 0 ) @@ -90,7 +90,7 @@ void tgChopper::Add( const tgPolygon& subject, const std::string& type ) // We just have a single row - no need to intersect first SG_LOG( SG_GENERAL, SG_DEBUG, " UN_CLIPPED row - center lat is " << b_min.get_center_lat() ); - ClipRow( subject, b_min.get_center_lat(), type ); + ClipRow( subject, b_min.get_center_lat(), type); } else { @@ -117,7 +117,7 @@ void tgChopper::Add( const tgPolygon& subject, const std::string& type ) clip_row.AddNode( 0, SGGeod::fromDeg( 180.0, clip_top) ); clip_row.AddNode( 0, SGGeod::fromDeg(-180.0, clip_top) ); - clipped = tgPolygon::Intersect( subject, clip_row ); + clipped = tgPolygon::Intersect( subject, clip_row); if ( clipped.TotalNodes() > 0 ) { if ( subject.GetPreserve3D() ) { @@ -205,7 +205,7 @@ void tgChopper::Save( bool DebugShapefiles ) long int poly_index = GenerateIndex( path ); sprintf( poly_ext, "%ld", poly_index ); - polyfile = polyfile + "." + poly_ext; + polyfile = polyfile + "." + poly_ext + "." + extra_extension; gzFile fp; if ( (fp = gzopen( polyfile.c_str(), "wb9" )) == NULL ) { diff --git a/src/Lib/terragear/tg_chopper.hxx b/src/Lib/terragear/tg_chopper.hxx index 47546192..e01f0215 100644 --- a/src/Lib/terragear/tg_chopper.hxx +++ b/src/Lib/terragear/tg_chopper.hxx @@ -11,10 +11,14 @@ class tgChopper public: tgChopper( const std::string& path ) { root_path = path; + extra_extension = ""; } void Add( const tgPolygon& poly, const std::string& type ); void Save( bool DebugShapes ); + void Add_Extension( const std::string& extension) { + extra_extension = extension; + } private: long int GenerateIndex( std::string path ); @@ -25,4 +29,5 @@ private: std::string root_path; bucket_polys_map bp_map; SGMutex lock; + std::string extra_extension; //add at end of file name }; diff --git a/src/Lib/terragear/tg_contour.cxx b/src/Lib/terragear/tg_contour.cxx index 2937a5fa..661279de 100644 --- a/src/Lib/terragear/tg_contour.cxx +++ b/src/Lib/terragear/tg_contour.cxx @@ -111,7 +111,11 @@ Then the line segments intersect if 0 <= t,u <= 1. double crossx = x1-nx1; double crossy = y1-ny1; double t = (crossx*nydif - crossy*nxdif)/denom; double u = -1*(xdif*crossy - ydif*crossx)/denom; - if (t >= 0.0 && t <= 1.0 && u >= 0.0 && u <= 1.0) intersect_ct++; + // We consider that an intersection at the edge of the line have + // not crossed + // over, that is, they lie on the same side, so we do not + // include equality in the comparisons + if (t > 0.0 && t < 1.0 && u > 0.0 && u < 1.0) intersect_ct++; } } } @@ -848,14 +852,16 @@ tgContour tgContour::AddColinearNodes( const tgContour& subject, std::vector node_list; bool hole; + bool keep_open; //If non-closed contour, keep open }; typedef std::vector tgcontour_list; diff --git a/src/Lib/terragear/tg_polygon.hxx b/src/Lib/terragear/tg_polygon.hxx index 0329d089..1cf7cef7 100644 --- a/src/Lib/terragear/tg_polygon.hxx +++ b/src/Lib/terragear/tg_polygon.hxx @@ -243,6 +243,7 @@ class tgPolygon public: tgPolygon() { preserve3d = false; + closed = true; } ~tgPolygon() { contours.clear(); @@ -351,6 +352,18 @@ public: flag = f; } + void SetOpen( void ) { //Do not try to close the contours + closed = false; + } + + void SetClosed (void) { + closed = true; + } + + bool IsClosed( void ) const { + return closed; + } + bool GetPreserve3D( void ) const { return preserve3d; } @@ -436,6 +449,7 @@ public: // Conversions static ClipperLib::Paths ToClipper( const tgPolygon& subject ); static tgPolygon FromClipper( const ClipperLib::Paths& subject ); + static tgPolygon FromClipper( const ClipperLib::PolyTree& subject ); static void ToClipperFile( const tgPolygon& subject, const std::string& path, const std::string& filename ); // T-Junctions and segment search @@ -460,6 +474,7 @@ private: bool preserve3d; unsigned int id; // unique polygon id for debug tgTexParams tp; + bool closed; // if we treat it as a closed shape }; #endif // _POLYGON_HXX diff --git a/src/Lib/terragear/tg_polygon_clip.cxx b/src/Lib/terragear/tg_polygon_clip.cxx index 359f9ef5..ec1c8436 100644 --- a/src/Lib/terragear/tg_polygon_clip.cxx +++ b/src/Lib/terragear/tg_polygon_clip.cxx @@ -136,7 +136,8 @@ tgPolygon tgPolygon::Diff( const tgPolygon& subject, tgPolygon& clip ) return result; } -tgPolygon tgPolygon::Intersect( const tgPolygon& subject, const tgPolygon& clip ) +//Intersect will keep open paths open +tgPolygon tgPolygon::Intersect( const tgPolygon& subject, const tgPolygon& clip) { tgPolygon result; UniqueSGGeodSet all_nodes; @@ -156,17 +157,23 @@ tgPolygon tgPolygon::Intersect( const tgPolygon& subject, const tgPolygon& clip ClipperLib::Paths clipper_subject = tgPolygon::ToClipper( subject ); ClipperLib::Paths clipper_clip = tgPolygon::ToClipper( clip ); - ClipperLib::Paths clipper_result; + ClipperLib::Paths clipper_result; // for closed polygons + ClipperLib::PolyTree clipper_tree_result; //for open polygons ClipperLib::Clipper c; c.Clear(); - c.AddPaths(clipper_subject, ClipperLib::ptSubject, true); + c.AddPaths(clipper_subject, ClipperLib::ptSubject, subject.IsClosed()); c.AddPaths(clipper_clip, ClipperLib::ptClip, true); - c.Execute(ClipperLib::ctIntersection, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); + if(subject.IsClosed()) { + c.Execute(ClipperLib::ctIntersection, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); - result = tgPolygon::FromClipper( clipper_result ); + result = tgPolygon::FromClipper( clipper_result ); + } + else { + c.Execute(ClipperLib::ctIntersection, clipper_tree_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); + result = tgPolygon::FromClipper( clipper_tree_result ); + } result = tgPolygon::AddColinearNodes( result, all_nodes ); - result.SetMaterial( subject.GetMaterial() ); result.SetTexParams( subject.GetTexParams() ); result.SetId( subject.GetId() ); @@ -199,6 +206,17 @@ tgPolygon tgPolygon::FromClipper( const ClipperLib::Paths& subject ) return result; } +// A polytree is returned when an open polygon has been clipped +tgPolygon tgPolygon::FromClipper( const ClipperLib::PolyTree& subject ) +{ + ClipperLib::Paths path_result; + tgPolygon result; + ClipperLib::PolyTreeToPaths(subject,path_result); + result = FromClipper(path_result); + return result; +} + + ClipperLib::Path tgTriangle::ToClipper( const tgTriangle& subject ) { ClipperLib::Path contour;