diff --git a/src/BuildTiles/Main/tgconstruct.hxx b/src/BuildTiles/Main/tgconstruct.hxx
index 04cae17e..fda359c9 100644
--- a/src/BuildTiles/Main/tgconstruct.hxx
+++ b/src/BuildTiles/Main/tgconstruct.hxx
@@ -124,13 +124,13 @@ private:
     int  LoadLandclassPolys( void );
     // Load Data Helpers
     bool load_poly(const std::string& path);
-    void add_poly(int area, const TGPolygon &poly, std::string material);
+    void add_poly(int area, tgPolygon& poly, std::string material);
 
     // Clip Data
     bool ClipLandclassPolys( void );
     // Clip Helpers
     void move_slivers( TGPolygon& in, TGPolygon& out );
-    void merge_slivers( TGLandclass& clipped, poly_list& slivers_list );
+    void merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_list );
 
     // Shared edge Matching
     void SaveSharedEdgeDataStage2( void );
@@ -164,7 +164,7 @@ private:
     void CalcPointNormals( void );
     void CalcTextureCoordinates( void );
     // Helpers
-    SGVec3d   calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 );
+    SGVec3f   calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 );
     TGPolygon linear_tex_coords( const TGPolygon& tri, const TGTexParams& tp );
     TGPolygon area_tex_coords( const TGPolygon& tri );
 
@@ -173,8 +173,7 @@ private:
     void AddCustomObjects( void );
 
     // Misc
-    void calc_normals( std::vector<SGVec3d>& wgs84_nodes, TGSuperPoly& sp );
-    double calc_tri_area( int_list& triangle_nodes );
+    void calc_normals( std::vector<SGGeod>& geod_nodes, std::vector<SGVec3d>& wgs84_nodes, tgPolygon& sp );
 
     // debug
     bool IsDebugShape( unsigned int id );
diff --git a/src/BuildTiles/Main/tgconstruct_cleanup.cxx b/src/BuildTiles/Main/tgconstruct_cleanup.cxx
index 15a6bb8f..b97d4a70 100644
--- a/src/BuildTiles/Main/tgconstruct_cleanup.cxx
+++ b/src/BuildTiles/Main/tgconstruct_cleanup.cxx
@@ -39,16 +39,18 @@ using std::string;
 
 void TGConstruct::FixTJunctions( void ) {
     int before, after;
+    std::vector<SGGeod> points;
+    nodes.get_geod_nodes( points );
 
     // traverse each poly, and add intermediate nodes
     for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
         for( unsigned int j = 0; j < polys_clipped.area_size(i); ++j ) {
             for( unsigned int k = 0; k < polys_clipped.shape_size(i, j); ++k ) {
-                TGPolygon current = polys_clipped.get_poly(i, j, k);
+                tgPolygon current = polys_clipped.get_poly(i, j, k);
 
-                before  = current.total_size();
-                current = add_tgnodes_to_poly( current, &nodes );
-                after   = current.total_size();
+                before  = current.TotalNodes();
+                current = tgPolygon::AddColinearNodes( current, points );
+                after   = current.TotalNodes();
 
                 if (before != after) {
                    SG_LOG( SG_CLIPPER, SG_INFO, "Fixed T-Junctions in " << get_area_name( (AreaType)i ) << ":" << j+1 << "-" << k << " of " << (int)polys_clipped.area_size(i) << " nodes increased from " << before << " to " << after );
@@ -67,69 +69,35 @@ void TGConstruct::FixTJunctions( void ) {
 // a polygon with no increased contours (i.e. the sliver is adjacent
 // and can be merged.)  If so, replace the clipped polygon with the
 // new polygon that has the sliver merged in.
-void TGConstruct::merge_slivers( TGLandclass& clipped,  poly_list& slivers_list ) {
-    TGPolygon poly, result, slivers, sliver;
-    point_list contour;
-    int original_contours, result_contours;
-    bool done;
-    int area, shape, segment, i, j;
-    int merged = 0;
-    int total = 0;
+void TGConstruct::merge_slivers( TGLandclass& clipped,  tgcontour_list& sliver_list ) {
+    for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES && sliver_list.size(); ++area ) {
+        if ( is_hole_area( area ) ) {
+            // don't merge a non-hole sliver in with a hole
+            continue;
+        }
 
-    for ( i = 0; i < (int)slivers_list.size(); i++ ) {
-        slivers = slivers_list[i];
+        for ( unsigned int s = 0; s < clipped.area_size(area) && sliver_list.size(); ++s ) {
+            TGShape shape = clipped.get_shape( area, s );
 
-        for ( j = 0; j < slivers.contours(); ++j ) {
-            // make the sliver polygon
-            contour = slivers.get_contour( j );
-            total++;
+            unsigned int before = sliver_list.size();
+            sliver_list = tgPolygon::MergeSlivers( shape.polys, sliver_list );
+            unsigned int after = sliver_list.size();
 
-            sliver.erase();
-            sliver.add_contour( contour, 0 );
-            done = false;
+            if (before != after) {
+                shape.BuildMask();
 
-            for ( area = 0; area < TG_MAX_AREA_TYPES && !done; ++area ) {
-                if ( is_hole_area( area ) ) {
-                    // don't merge a non-hole sliver in with a hole
-                    continue;
-                }
-
-                for ( shape = 0; shape < (int)clipped.area_size(area) && !done; ++shape ) {
-                    unsigned int shape_id = clipped.get_shape( area, shape ).id;
-
-                    for ( segment = 0; segment < (int)clipped.shape_size(area, shape) && !done; ++segment ) {
-
-                        poly = clipped.get_poly( area, shape, segment );
-                        original_contours = poly.contours();
-                        result = tgPolygonUnion( poly, sliver );
-                        result_contours = result.contours();
-
-                        if ( original_contours == result_contours ) {
-                            SG_LOG(SG_GENERAL, SG_INFO, "MERGED SLIVER " << i << ", " << j << " into area " << get_area_name( (AreaType)area ) << " id: " << shape_id << " segment: " << segment  );
-
-                            clipped.set_poly( area, shape, segment, result );
-                            merged++;
-
-                            /* add the sliver to the clip_mask, too */
-                            TGPolygon mask = clipped.get_mask( area, shape );
-                            result = tgPolygonUnion( mask, sliver );
-                            clipped.set_mask( area, shape, result );
-
-                            if ( IsDebugShape( shape_id ) ) {
-                                WriteDebugShape( "with_slivers", clipped.get_shape( area, shape ) );
-                            }
-
-                            done = true;
-                        }
-                    }
+#if 0
+                if ( IsDebugShape( shape.id ) ) {
+                    WriteDebugShape( "with_slivers", shape );
                 }
+#endif
             }
         }
     }
 
-    slivers_list.clear();
+    SG_LOG(SG_GENERAL, SG_INFO, " UNMERGED SLIVERS: " << sliver_list.size() );
 
-    SG_LOG(SG_GENERAL, SG_INFO, " UNMERGED SLIVERS: " << total - merged );
+    sliver_list.clear();
 }
 
 void TGConstruct::CleanClippedPolys() {
@@ -141,35 +109,35 @@ void TGConstruct::CleanClippedPolys() {
 
             // step 1 : snap
             for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
-                TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
-                poly = snap(poly, gSnap);
+                tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
+                poly = tgPolygon::Snap(poly, gSnap);
                 polys_clipped.set_poly( area, shape, segment, poly );
             }
 
             if ( IsDebugShape( id ) ) {
-                WriteDebugShape( "snapped", polys_clipped.get_shape( area, shape ) );
+                tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "snapped", "" );
             }
 
             // step 2 : remove_dups
             for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
-                TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
-                poly = remove_dups( poly );
+                tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
+                poly = tgPolygon::RemoveDups( poly );
                 polys_clipped.set_poly( area, shape, segment, poly );
             }
 
             if ( IsDebugShape( id ) ) {
-                WriteDebugShape( "rem dupes", polys_clipped.get_shape( area, shape ) );
+                tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "rem_dups", "" );
             }
 
             // step 3 : remove_bad_contours
             for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
-                TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
-                poly = remove_bad_contours( poly );
+                tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
+                poly = tgPolygon::RemoveBadContours( poly );
                 polys_clipped.set_poly( area, shape, segment, poly );
             }
 
             if ( IsDebugShape( id ) ) {
-                WriteDebugShape( "rem bad contours", polys_clipped.get_shape( area, shape ) );
+                tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "rem_bcs", "" );
             }
 
 // todo - add up all segments in a shape for printout
diff --git a/src/BuildTiles/Main/tgconstruct_clip.cxx b/src/BuildTiles/Main/tgconstruct_clip.cxx
index 2fd6df4b..e436f4c2 100644
--- a/src/BuildTiles/Main/tgconstruct_clip.cxx
+++ b/src/BuildTiles/Main/tgconstruct_clip.cxx
@@ -31,12 +31,12 @@
 using std::string;
 
 bool TGConstruct::ClipLandclassPolys( void ) {
-    TGPolygon clipped, tmp;
-    TGPolygon remains;
-    TGPolygon safety_base;
-    poly_list slivers;
+    tgPolygon clipped, tmp;
+    tgPolygon remains;
+    tgPolygon safety_base;
+    tgcontour_list slivers;
     int i, j;
-    Point3D p;
+    SGGeod p;
     SGVec2d min, max;
     bool debug_area, debug_shape;
     static int accum_idx = 0;
@@ -47,118 +47,118 @@ bool TGConstruct::ClipLandclassPolys( void ) {
     max.x() = bucket.get_center_lon() + 0.5 * bucket.get_width();
     max.y() = bucket.get_center_lat() + 0.5 * bucket.get_height();
 
-    tgPolygonInitClipperAccumulator();
+    tgAccumulator accum;
 
     // set up clipping tile : and remember to add the nodes!
-    safety_base.erase();
+    p = SGGeod::fromDegM( min.x(), min.y(), -9999.0 );
+    safety_base.AddNode( 0, p );
+    nodes.unique_add( p );
 
-    p = Point3D(min.x(), min.y(), -9999.0);
-    safety_base.add_node( 0, p );
-    nodes.unique_add( p.toSGGeod() );
+    p = SGGeod::fromDegM( max.x(), min.y(), -9999.0 );
+    safety_base.AddNode( 0, p );
+    nodes.unique_add( p );
 
-    p = Point3D(max.x(), min.y(), -9999.0);
-    safety_base.add_node( 0, p );
-    nodes.unique_add( p.toSGGeod() );
+    p = SGGeod::fromDegM( max.x(), max.y(), -9999.0 );
+    safety_base.AddNode( 0, p );
+    nodes.unique_add( p );
 
-    p = Point3D(max.x(), max.y(), -9999.0);
-    safety_base.add_node( 0, p );
-    nodes.unique_add( p.toSGGeod() );
-
-    p = Point3D(min.x(), max.y(), -9999.0);
-    safety_base.add_node( 0, p );
-    nodes.unique_add( p.toSGGeod() );
+    p = SGGeod::fromDegM( min.x(), max.y(), -9999.0 );
+    safety_base.AddNode( 0, p );
+    nodes.unique_add( p );
 
     // set up land mask, we clip most things to this since it is our
     // best representation of land vs. ocean.  If we have other less
     // accurate data that spills out into the ocean, we want to just
     // clip it.
     // also set up a mask for all water and islands
-    TGPolygon land_mask, water_mask, island_mask;
-    land_mask.erase();
-    water_mask.erase();
-    island_mask.erase();
+    tgPolygon land_mask, water_mask, island_mask;
+    tgpolygon_list land_list, water_list, island_list;
 
     for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) {
         if ( is_landmass_area( i ) && !ignoreLandmass ) {
             for ( unsigned int j = 0; j < polys_in.area_size(i); ++j ) {
-                land_mask = tgPolygonUnion( polys_in.get_mask(i, j), land_mask );
+                land_list.push_back( polys_in.get_mask(i, j) );
             }
 
         } else if ( is_water_area( i ) ) {
             for (unsigned int j = 0; j < polys_in.area_size(i); j++) {
-                water_mask = tgPolygonUnion( polys_in.get_mask(i, j), water_mask );
+                water_list.push_back( polys_in.get_mask(i, j) );
             }
         } else if ( is_island_area( i ) ) {
             for (unsigned int j = 0; j < polys_in.area_size(i); j++) {
-                island_mask = tgPolygonUnion( polys_in.get_mask(i, j), island_mask );
+                island_list.push_back( polys_in.get_mask(i, j) );
             }
         }
     }
 
+    land_mask   = tgPolygon::Union( land_list );
+    water_mask  = tgPolygon::Union( water_list );
+    island_mask = tgPolygon::Union( island_list );
+
     // Dump the masks
     if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
-        WriteDebugPoly( "land_mask", "", land_mask );
-        WriteDebugPoly( "water_mask", "", water_mask );
-        WriteDebugPoly( "island_mask", "", island_mask );
+        tgPolygon::ToShapefile( land_mask, ds_name, "land_mask", "" );
+        tgPolygon::ToShapefile( water_mask, ds_name, "water_mask", "" );
+        tgPolygon::ToShapefile( island_mask, ds_name, "island_mask", "" );
     }
 
     // process polygons in priority order
     for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
         debug_area = IsDebugArea( i );
         for( j = 0; j < (int)polys_in.area_size(i); ++j ) {
-            TGPolygon current = polys_in.get_mask(i, j);
+            tgPolygon current = polys_in.get_mask(i, j);
             debug_shape = IsDebugShape( polys_in.get_shape( i, j ).id );
 
             SG_LOG( SG_CLIPPER, SG_INFO, "Clipping " << get_area_name( (AreaType)i ) << "(" << i << "):" << j+1 << " of " << polys_in.area_size(i) << " id " << polys_in.get_shape( i, j ).id );
 
             tmp = current;
 
-
             // if not a hole, clip the area to the land_mask
             if ( !ignoreLandmass && !is_hole_area( i ) ) {
-                tmp = tgPolygonInt( tmp, land_mask );
+                tmp = tgPolygon::Intersect( tmp, land_mask );
             }
 
             // if a water area, cut out potential islands
             if ( is_water_area( i ) ) {
                 // clip against island mask
-                tmp = tgPolygonDiff( tmp, island_mask );
+                tmp = tgPolygon::Diff( tmp, island_mask );
 
             }
 
             if ( debug_area || debug_shape ) {
                 char layer[32];
                 char name[32];
+
                 sprintf(layer, "pre_clip_%d", polys_in.get_shape( i, j ).id );
                 sprintf(name, "shape %d,%d", i,j);
-                WriteDebugPoly( layer, name, tmp );
+                tgPolygon::ToShapefile( tmp, ds_name, layer, name );
 
                 sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_shape( i, j ).id );
-                sprintf(name, "shape_accum %d,%d", i,j);
-
-                tgPolygonDumpAccumulator( ds_name, layer, name );
+                accum.ToShapefiles( ds_name, layer );
             }
 
-            clipped = tgPolygonDiffClipperWithAccumulator( tmp );
+            clipped = accum.Diff( tmp );
 
             if ( debug_area || debug_shape ) {
                 char layer[32];
                 char name[32];
+
                 sprintf(layer, "post_clip_%d", polys_in.get_shape( i, j ).id );
                 sprintf(name, "shape %d,%d", i,j);
-                WriteDebugPoly( layer, name, clipped );
+
+                tgPolygon::ToShapefile( clipped, ds_name, layer, name );
             }
-            
+
             // only add to output list if the clip left us with a polygon
-            if ( clipped.contours() > 0 ) {
+            if ( clipped.Contours() > 0 ) {
 
 #if FIND_SLIVERS
                 // move slivers from clipped polygon to slivers polygon
-                tgPolygonFindSlivers( clipped, slivers );
+                tgPolygon::RemoveSlivers( clipped, slivers );
 #endif
 
                 // add the sliverless result polygon to the clipped polys list
-                if ( clipped.contours() > 0  ) {
+                if ( clipped.Contours() > 0  ) {
                     TGShape shape;
 
                     // copy all of the superpolys and texparams
@@ -166,40 +166,39 @@ bool TGConstruct::ClipLandclassPolys( void ) {
                     shape.textured = polys_in.get_textured( i, j );
                     shape.id  = polys_in.get_shape( i, j ).id;
 
-                    shape.area= polys_in.get_shape( i, j ).area;
-                    shape.sps = polys_in.get_shape( i, j ).sps;
-                    shape.tps = polys_in.get_shape( i, j ).tps;
+                    shape.area  = polys_in.get_shape( i, j ).area;
+                    shape.polys = polys_in.get_shape( i, j ).polys;
 
                     // shape.sps.push_back( sp );
                     polys_clipped.add_shape( i, shape );
 
+#if 0
                     if ( debug_area || debug_shape ) {
                         WriteDebugShape( "clipped", shape );
                     }
+#endif
                 }
             }
 
-            if ( debug_shape ) {
-                tgPolygonAddToClipperAccumulator( tmp, true );
-            } else {
-                tgPolygonAddToClipperAccumulator( tmp, false );
-            }
-
+            accum.Add( tmp );
             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);
 
-                tgPolygonDumpAccumulator( ds_name, layer, name );
+                accum.ToShapefiles( ds_name, layer );
             }
+
             accum_idx++;
         }
     }
 
     if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
         // Dump the sliver list
-        WriteDebugPolys( "poly_slivers", slivers );
+        char name[32];
+        for ( unsigned int i=0; i<slivers.size(); i++ ) {
+            sprintf( name, "sliver %4d", i );
+            tgContour::ToShapefile( slivers[i], ds_name, "slivers", name );
+        }
     }
 
 #if FIND_SLIVERS
@@ -210,51 +209,44 @@ bool TGConstruct::ClipLandclassPolys( void ) {
     slivers.clear();
 
     // finally, what ever is left over goes to ocean
-    remains = tgPolygonDiffClipperWithAccumulator( safety_base );
+    remains = accum.Diff( safety_base );
 
-    if ( remains.contours() > 0 ) {
+    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;
+        tgPolygon::RemoveSlivers( remains, slivers );
 
-#if FIND_SLIVERS
-        // merge any slivers with previously clipped
-        // neighboring polygons
         if ( slivers.size() > 0 ) {
 
             if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
                 // Dump the sliver list
-                WriteDebugPolys( "remains_slivers", slivers );
+                char name[32];
+                for ( unsigned int i=0; i<slivers.size(); i++ ) {
+                    sprintf( name, "sliver %4d", i );
+                    tgContour::ToShapefile( slivers[i], ds_name, "remains slivers", name );
+                }
             }
 
             merge_slivers(polys_clipped, slivers);
         }
 #endif
 
-        if ( remains.contours() > 0 ) {
-            TGSuperPoly sp;
+        if ( remains.Contours() > 0 ) {
             TGShape shape;
 
             string material = get_area_name(get_sliver_target_area_type());
+            remains.SetMaterial( material );
 
-            sp.set_material( material );
-            sp.set_poly( remains );
             shape.SetMask( remains );
             shape.textured = false;
-            shape.sps.push_back( sp );
+            shape.polys.push_back( remains );
 
             polys_clipped.add_shape( (int)get_sliver_target_area_type(), shape );
         }
     }
 
-    tgPolygonFreeClipperAccumulator();
-
     // 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++ ) {
@@ -267,14 +259,14 @@ bool TGConstruct::ClipLandclassPolys( void ) {
     for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
         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++) {
-                TGPolygon poly = polys_clipped.get_poly( area, shape, segment );
+                tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
 
                 SG_LOG( SG_CLIPPER, SG_INFO, "Collecting nodes for " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
 
-                for (int con=0; con < poly.contours(); con++) {
-                    for (int node = 0; node < poly.contour_size( con ); node++) {
+                for (unsigned int con=0; con < poly.Contours(); con++) {
+                    for (unsigned int node = 0; node < poly.ContourSize( con ); node++) {
                         // ensure we have all nodes...
-                        nodes.unique_add( poly.get_pt( con, node ).toSGGeod() );
+                        nodes.unique_add( poly.GetNode( con, node ) );
                     }
                 }
             }
diff --git a/src/BuildTiles/Main/tgconstruct_debug.cxx b/src/BuildTiles/Main/tgconstruct_debug.cxx
index ba3e4af6..a7566abb 100644
--- a/src/BuildTiles/Main/tgconstruct_debug.cxx
+++ b/src/BuildTiles/Main/tgconstruct_debug.cxx
@@ -133,6 +133,7 @@ bool TGConstruct::IsDebugArea( unsigned int area )
     return is_debug;
 }
 
+#if 0
 void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape )
 {
     char name[64];
@@ -141,7 +142,7 @@ void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape
     ds_id = tgShapefileOpenDatasource( ds_name );
     l_id  = tgShapefileOpenLayer( ds_id, layer_name );
 
-    tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, name );
+    tgShapefileCreateFeature( ds_id, l_id, shape.mask, name );
 
     // close after each write
     ds_id = tgShapefileCloseDatasource( ds_id );
@@ -171,6 +172,7 @@ void TGConstruct::WriteDebugPolys( const char* layer_name, const poly_list& poly
     // close after each write
     ds_id = tgShapefileCloseDatasource( ds_id );
 }
+#endif
 
 // TODO : Add to TGNodes class
 #if 0
diff --git a/src/BuildTiles/Main/tgconstruct_elevation.cxx b/src/BuildTiles/Main/tgconstruct_elevation.cxx
index 4968677d..d3c397ab 100644
--- a/src/BuildTiles/Main/tgconstruct_elevation.cxx
+++ b/src/BuildTiles/Main/tgconstruct_elevation.cxx
@@ -91,11 +91,10 @@ static double distanceSphere( const SGGeoc& p1, const SGGeod& p2 ) {
 // hopefully, this will get better when we have the area lookup via superpoly...
 void TGConstruct::CalcElevations( void )
 {
-    TGPolyNodes tri_nodes;
-    double e1, e2, e3, min;
-    int    n1, n2, n3;
     std::vector<SGGeod> raw_nodes;
     SGGeoc p;
+    double e1, e2, e3, min;
+    int    n1, n2, n3;
 
     SG_LOG(SG_GENERAL, SG_ALERT, "fixing node heights");
 
@@ -110,6 +109,7 @@ void TGConstruct::CalcElevations( void )
     }
 
     nodes.get_geod_nodes(raw_nodes);
+
     // now flatten some stuff
     for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
         if ( is_lake_area( (AreaType)area ) ) {
@@ -117,19 +117,14 @@ void TGConstruct::CalcElevations( void )
                 for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
 
                     SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
-                    tri_nodes = polys_clipped.get_tri_idxs( area, shape, segment );
+                    tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
 
-                    for (int tri=0; tri < tri_nodes.contours(); tri++) {
-                        if (tri_nodes.contour_size( tri ) != 3) {
-                            SG_LOG(SG_GENERAL, SG_ALERT, "triangle doesnt have 3 nodes" << tri_nodes.contour_size( tri ) );
-                            exit(0);
-                        }
-
-                        n1 = tri_nodes.get_pt( tri, 0 );
+                    for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
+                        n1 = poly.GetTriIdx( tri, 0 );
                         e1 = nodes.get_node(n1).GetPosition().getElevationM();
-                        n2 = tri_nodes.get_pt( tri, 1 );
+                        n2 = poly.GetTriIdx( tri, 1 );
                         e2 = nodes.get_node(n2).GetPosition().getElevationM();
-                        n3 = tri_nodes.get_pt( tri, 2 );
+                        n3 = poly.GetTriIdx( tri, 2 );
                         e3 = nodes.get_node(n3).GetPosition().getElevationM();
 
                         min = e1;
@@ -149,20 +144,14 @@ void TGConstruct::CalcElevations( void )
                 for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
 
                     SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
-                    tri_nodes = polys_clipped.get_tri_idxs( area, shape, segment );
+                    tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
 
-                    for (int tri=0; tri < tri_nodes.contours(); tri++) {
-                        if (tri_nodes.contour_size( tri ) != 3) {
-                            SG_LOG(SG_GENERAL, SG_ALERT, "triangle doesnt have 3 nodes" << tri_nodes.contour_size( tri ) );
-                            exit(0);
-                        }
-
-
-                        n1 = tri_nodes.get_pt( tri, 0 );
+                    for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
+                        n1 = poly.GetTriIdx( tri, 0 );
                         e1 = nodes.get_node(n1).GetPosition().getElevationM();
-                        n2 = tri_nodes.get_pt( tri, 1 );
+                        n2 = poly.GetTriIdx( tri, 1 );
                         e2 = nodes.get_node(n2).GetPosition().getElevationM();
-                        n3 = tri_nodes.get_pt( tri, 2 );
+                        n3 = poly.GetTriIdx( tri, 2 );
                         e3 = nodes.get_node(n3).GetPosition().getElevationM();
 
                         min = e1;
@@ -192,20 +181,14 @@ void TGConstruct::CalcElevations( void )
                 for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
 
                     SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
-                    tri_nodes = polys_clipped.get_tri_idxs( area, shape, segment );
+                    tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
 
-                    for (int tri=0; tri < tri_nodes.contours(); tri++) {
-                        if (tri_nodes.contour_size( tri ) != 3) {
-                            SG_LOG(SG_GENERAL, SG_ALERT, "triangle doesnt have 3 nodes" << tri_nodes.contour_size( tri ) );
-                            exit(0);
-                        }
-
-
-                        n1 = tri_nodes.get_pt( tri, 0 );
+                    for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
+                        n1 = poly.GetTriIdx( tri, 0 );
                         e1 = nodes.get_node(n1).GetPosition().getElevationM();
-                        n2 = tri_nodes.get_pt( tri, 1 );
+                        n2 = poly.GetTriIdx( tri, 1 );
                         e2 = nodes.get_node(n2).GetPosition().getElevationM();
-                        n3 = tri_nodes.get_pt( tri, 2 );
+                        n3 = poly.GetTriIdx( tri, 2 );
                         e3 = nodes.get_node(n3).GetPosition().getElevationM();
 
                         min = e1;
@@ -235,17 +218,12 @@ void TGConstruct::CalcElevations( void )
                 for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
 
                     SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
-                    tri_nodes = polys_clipped.get_tri_idxs( area, shape, segment );
+                    tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
 
-                    for (int tri=0; tri < tri_nodes.contours(); tri++) {
-                        if (tri_nodes.contour_size( tri ) != 3) {
-                            SG_LOG(SG_GENERAL, SG_ALERT, "triangle doesnt have 3 nodes" << tri_nodes.contour_size( tri ) );
-                            exit(0);
-                        }
-
-                        n1 = tri_nodes.get_pt( tri, 0 );
-                        n2 = tri_nodes.get_pt( tri, 1 );
-                        n3 = tri_nodes.get_pt( tri, 2 );
+                    for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
+                        n1 = poly.GetTriIdx( tri, 0 );
+                        n2 = poly.GetTriIdx( tri, 1 );
+                        n3 = poly.GetTriIdx( tri, 2 );
 
                         nodes.SetElevation( n1, 0.0 );
                         nodes.SetElevation( n2, 0.0 );
diff --git a/src/BuildTiles/Main/tgconstruct_landclass.cxx b/src/BuildTiles/Main/tgconstruct_landclass.cxx
index 62021048..76166f74 100644
--- a/src/BuildTiles/Main/tgconstruct_landclass.cxx
+++ b/src/BuildTiles/Main/tgconstruct_landclass.cxx
@@ -217,12 +217,13 @@ static void fix_land_cover_assignments( TGConstruct& c ) {
 int TGConstruct::load_landcover()
 {
     int count = 0;
+#if 0
 
     try {
 
         LandCover cover(get_cover());
-        TGPolygon polys[TG_MAX_AREA_TYPES];
-        TGPolygon poly;     // working polygon
+        tgPolygon polys[TG_MAX_AREA_TYPES];
+        tgPolygon poly;     // working polygon
 
         // Get the lower left (SW) corner of the tile
         double base_lon = bucket.get_center_lon()
@@ -275,6 +276,7 @@ int TGConstruct::load_landcover()
         exit(-1);
     }
 
+#endif
     // Return the number of polygons actually read.
     return count;
 }
diff --git a/src/BuildTiles/Main/tgconstruct_lookup.cxx b/src/BuildTiles/Main/tgconstruct_lookup.cxx
index 4cf6b493..c00d44ec 100644
--- a/src/BuildTiles/Main/tgconstruct_lookup.cxx
+++ b/src/BuildTiles/Main/tgconstruct_lookup.cxx
@@ -40,22 +40,21 @@ void TGConstruct::LookupNodesPerVertex( void )
     for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
         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++ ) {
-                TGPolygon   tris = polys_clipped.get_tris( area, shape, segment );
-                TGPolyNodes tri_nodes;
-                int         idx;
+                tgPolygon   poly = polys_clipped.get_poly( area, shape, segment );
 
-                for (int tri=0; tri < tris.contours(); tri++) {
-                    for (int vertex = 0; vertex < tris.contour_size(tri); vertex++) {
-                        idx = nodes.find( tris.get_pt( tri, vertex ).toSGGeod() );
+                for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
+                    for (unsigned int vertex = 0; vertex < 3; vertex++) {
+                        int idx = nodes.find( poly.GetTriNode( tri, vertex ) );
                         if (idx >= 0) {
-                            tri_nodes.add_node( tri, idx );
+                            poly.SetTriIdx( tri, vertex, idx );
                         } else {
-                            SG_LOG(SG_GENERAL, SG_ALERT, "didn't find vertex! " << tris.get_pt( tri, vertex ) );
+                            SG_LOG(SG_GENERAL, SG_ALERT, "didn't find vertex! " << poly.GetTriNode( tri, vertex ) );
                             exit(0);
                         }
                     }
                 }
-                polys_clipped.set_tri_idxs(area, shape, segment, tri_nodes);
+
+                polys_clipped.set_poly( area, shape, segment, poly );
             }
         }
     }
@@ -69,12 +68,12 @@ void TGConstruct::LookupFacesPerNode( void )
     for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
         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++ ) {
-                TGPolygon   tris = polys_clipped.get_tris(area, shape, segment);
+                tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
 
-                for (int tri=0; tri < tris.contours(); tri++) {
-                    for (int sub = 0; sub < tris.contour_size(tri); sub++) {
-                        int n = nodes.find( tris.get_pt( tri, sub ).toSGGeod() );
-                        nodes.AddFace( n, area, shape, segment, tri );
+                for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
+                    for (int v = 0; v < 3; v++) {
+                        int i = poly.GetTriIdx( tri, v );
+                        nodes.AddFace( i, area, shape, segment, tri );
                     }
                 }
             }
diff --git a/src/BuildTiles/Main/tgconstruct_math.cxx b/src/BuildTiles/Main/tgconstruct_math.cxx
index 481c4907..0c02a822 100644
--- a/src/BuildTiles/Main/tgconstruct_math.cxx
+++ b/src/BuildTiles/Main/tgconstruct_math.cxx
@@ -31,6 +31,7 @@
 
 //using std::string;
 
+#if 0
 double TGConstruct::calc_tri_area( int_list& triangle_nodes ) {
     SGGeod p1 = nodes.get_node( triangle_nodes[0] ).GetPosition();
     SGGeod p2 = nodes.get_node( triangle_nodes[1] ).GetPosition();
@@ -38,9 +39,11 @@ double TGConstruct::calc_tri_area( int_list& triangle_nodes ) {
 
     return triangle_area( p1, p2, p3 );
 }
+#endif
 
-SGVec3d TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) {
-    SGVec3d v1, v2, normal;
+SGVec3f TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) {
+    SGVec3f v1, v2;
+    SGVec3f normal;
 
     // do some sanity checking.  With the introduction of landuse
     // areas, we can get some long skinny triangles that blow up our
@@ -62,7 +65,7 @@ SGVec3d TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d&
     }
 
     if ( degenerate ) {
-        normal = normalize(SGVec3d(p1.x(), p1.y(), p1.z()));
+        normal = normalize(SGVec3f(p1.x(), p1.y(), p1.z()));
     } else {
         v1[0] = p2.x() - p1.x();
         v1[1] = p2.y() - p1.y();
@@ -76,34 +79,26 @@ SGVec3d TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d&
     return normal;
 }
 
-void TGConstruct::calc_normals( std::vector<SGVec3d>& wgs84_nodes, TGSuperPoly& sp ) {
+void TGConstruct::calc_normals( std::vector<SGGeod>& geod_nodes, std::vector<SGVec3d>& wgs84_nodes, tgPolygon& poly ) {
     // for each face in the superpoly, calculate a face normal
-    SGVec3d     normal;
-    TGPolyNodes tri_nodes = sp.get_tri_idxs();
-    int_list    face_nodes;
-    double_list face_areas;
-    point_list  face_normals;
+    SGVec3f     normal;
     double      area;
 
-    face_normals.clear();
-    face_areas.clear();
+    for (unsigned int tri = 0; tri < poly.Triangles(); tri++) {
+        SGGeod g1 = geod_nodes[ poly.GetTriIdx( tri, 0 ) ];
+        SGGeod g2 = geod_nodes[ poly.GetTriIdx( tri, 1 ) ];
+        SGGeod g3 = geod_nodes[ poly.GetTriIdx( tri, 2 ) ];
 
-    for (int i=0; i<tri_nodes.contours(); i++) {
-        face_nodes = tri_nodes.get_contour(i);
+        SGVec3d v1 = wgs84_nodes[ poly.GetTriIdx( tri, 0 ) ];
+        SGVec3d v2 = wgs84_nodes[ poly.GetTriIdx( tri, 1 ) ];
+        SGVec3d v3 = wgs84_nodes[ poly.GetTriIdx( tri, 2 ) ];
 
-        SGVec3d p1 = wgs84_nodes[ face_nodes[0] ];
-        SGVec3d p2 = wgs84_nodes[ face_nodes[1] ];
-        SGVec3d p3 = wgs84_nodes[ face_nodes[2] ];
+        area   = triangle_area( g1, g2, g3 );
+        normal = calc_normal( area, v1, v2, v3 );
 
-        area  = calc_tri_area( face_nodes );
-        normal = calc_normal( area, p1, p2, p3 );
-
-        face_normals.push_back( Point3D::fromSGVec3( normal ) );
-        face_areas.push_back( area );
+        poly.SetTriFaceArea( tri, area );
+        poly.SetTriFaceNormal( tri, normal );
     }
-
-    sp.set_face_normals( face_normals );
-    sp.set_face_areas( face_areas );
 }
 
 void TGConstruct::CalcFaceNormals( void )
@@ -112,11 +107,14 @@ void TGConstruct::CalcFaceNormals( void )
     std::vector<SGVec3d> wgs84_nodes;
     nodes.get_wgs84_nodes( wgs84_nodes );
 
+    std::vector<SGGeod>  geod_nodes;
+    nodes.get_geod_nodes( geod_nodes );
+
     for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
         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, "Calculating face normals for " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << polys_in.area_size(area) );
-                calc_normals( wgs84_nodes, polys_clipped.get_superpoly( area, shape, segment ) );
+                calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, shape, segment ) );
             }
         }
     }
@@ -156,10 +154,8 @@ void TGConstruct::CalcPointNormals( void )
             unsigned int shape   = faces[j].shape;
             unsigned int segment = faces[j].seg;
             unsigned int tri     = faces[j].tri;
-            int_list     face_nodes;
 
             normal     = polys_clipped.get_face_normal( at, shape, segment, tri ).toSGVec3d();
-            face_nodes = polys_clipped.get_tri_idxs( at, shape, segment ).get_contour( tri ) ;
             face_area  = polys_clipped.get_face_area( at, shape, segment, tri );
 
             normal *= face_area;    // scale normal weight relative to area
diff --git a/src/BuildTiles/Main/tgconstruct_output.cxx b/src/BuildTiles/Main/tgconstruct_output.cxx
index 4b27acf2..208a7c4a 100644
--- a/src/BuildTiles/Main/tgconstruct_output.cxx
+++ b/src/BuildTiles/Main/tgconstruct_output.cxx
@@ -29,7 +29,9 @@
 #include <simgear/io/sg_binobj.hxx>
 #include <simgear/structure/exception.hxx>
 #include <simgear/debug/logstream.hxx>
-#include <Geometry/trinodes.hxx>
+
+#include <Polygon/tg_unique_vec3f.hxx>
+#include <Polygon/tg_unique_vec2f.hxx>
 
 #include "tgconstruct.hxx"
 
@@ -111,9 +113,8 @@ void TGConstruct::AddCustomObjects( void ) {
 
 void TGConstruct::WriteBtgFile( void )
 {
-    TGTriNodes normals, texcoords;
-    normals.clear();
-    texcoords.clear();
+    UniqueSGVec3fSet normals;
+    UniqueSGVec2fSet texcoords;
 
     group_list pts_v; pts_v.clear();
     group_list pts_n; pts_n.clear();
@@ -134,6 +135,8 @@ void TGConstruct::WriteBtgFile( void )
     int_list pt_n, tri_n, strip_n;
     int_list tri_tc, strip_tc;
 
+    SG_LOG(SG_GENERAL, SG_INFO, "Output triangles" );
+
     for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
         // only tesselate non holes
         if ( !is_hole_area( area ) ) {
@@ -142,24 +145,24 @@ void TGConstruct::WriteBtgFile( void )
                     SG_LOG( SG_CLIPPER, SG_INFO, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" <<
                             shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
 
-                    TGPolyNodes tri_nodes = polys_clipped.get_tri_idxs(area, shape, segment);
-                    TGPolygon   tri_txs   = polys_clipped.get_texcoords(area, shape, segment);
+                    tgPolygon   poly      = polys_clipped.get_poly(area, shape, segment);
                     string      material  = polys_clipped.get_material(area, shape, segment);
 
-                    for (int k = 0; k < tri_nodes.contours(); ++k) {
+                    SG_LOG(SG_GENERAL, SG_INFO, "  num tris " << poly.Triangles() );
+
+                    for (unsigned int k = 0; k < poly.Triangles(); ++k) {
                         tri_v.clear();
                         tri_n.clear();
                         tri_tc.clear();
-                        for (int l = 0; l < tri_nodes.contour_size(k); ++l) {
-                            index = tri_nodes.get_pt( k, l );
+                        for (int l = 0; l < 3; ++l) {
+                            index = poly.GetTriIdx( k, l );
                             tri_v.push_back( index );
 
                             // add the node's normal
-                            index = normals.unique_add( Point3D::fromSGVec3( nodes.GetNormal( index ) ) );
+                            index = normals.add( nodes.GetNormal( index ) );
                             tri_n.push_back( index );
 
-                            Point3D tc = tri_txs.get_pt( k, l );
-                            index = texcoords.unique_add( tc );
+                            index = texcoords.add( poly.GetTriTexCoord( k, l ) );
                             tri_tc.push_back( index );
                         }
                         tris_v.push_back( tri_v );
@@ -167,6 +170,8 @@ void TGConstruct::WriteBtgFile( void )
                         tris_tc.push_back( tri_tc );
 
                         material  = polys_clipped.get_material(area, shape, segment);
+                        SG_LOG(SG_GENERAL, SG_INFO, "Add tri material " << material);
+
                         tri_materials.push_back( material );
                     }
                 }
@@ -203,27 +208,13 @@ void TGConstruct::WriteBtgFile( void )
     string txtname = bucket.gen_index_str();
     txtname += ".txt";
 
-    std::vector< SGVec3f > normals_3f;
-    for (int i=0; i < (int)normals.get_node_list().size(); i++ )
-    {
-        Point3D node = normals.get_node_list()[i];
-        normals_3f.push_back( node.toSGVec3f() );
-    }
-
-    std::vector< SGVec2f > texcoords_2f;
-    for (int i=0; i < (int)texcoords.get_node_list().size(); i++ )
-    {
-        Point3D node = texcoords.get_node_list()[i];
-        texcoords_2f.push_back( node.toSGVec2f() );
-    }
-
     SGBinObject obj;
 
     obj.set_gbs_center( gbs_center );
     obj.set_gbs_radius( gbs_radius );
     obj.set_wgs84_nodes( wgs84_nodes );
-    obj.set_normals( normals_3f );
-    obj.set_texcoords( texcoords_2f );
+    obj.set_normals( normals.get_list() );
+    obj.set_texcoords( texcoords.get_list() );
     obj.set_pts_v( pts_v );
     obj.set_pts_n( pts_n );
     obj.set_pt_materials( pt_materials );
diff --git a/src/BuildTiles/Main/tgconstruct_poly.cxx b/src/BuildTiles/Main/tgconstruct_poly.cxx
index 9dbf4cac..cf76696b 100644
--- a/src/BuildTiles/Main/tgconstruct_poly.cxx
+++ b/src/BuildTiles/Main/tgconstruct_poly.cxx
@@ -38,16 +38,12 @@ using std::string;
 static unsigned int cur_poly_id = 0;
 
 // Add a polygon to the clipper. - only used by load_osgb36_poly - make that function more like ogr load
-void TGConstruct::add_poly( int area, const TGPolygon &poly, string material ) {
+void TGConstruct::add_poly( int area, tgPolygon &poly, string material ) {
     TGShape shape;
-    TGSuperPoly sp;
 
     if ( area < TG_MAX_AREA_TYPES ) {
-        sp.set_poly( poly );
-        sp.set_material( material );
-
-        shape.sps.push_back( sp );
-
+        poly.SetMaterial( material );
+        shape.polys.push_back( poly );
         polys_in.add_shape( area, shape );
     } else {
         SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon type out of range = " << area);
@@ -73,9 +69,8 @@ bool TGConstruct::load_poly(const string& path) {
         exit(-1);
     }
 
-    TGPolygon   poly;
-    TGTexParams tp;
-    Point3D     p;
+    tgPolygon   poly;
+    tgTexParams tp;
 
     // (this could break things, why is it here) in >> skipcomment;
     while ( !in.eof() ) {
@@ -120,40 +115,29 @@ bool TGConstruct::load_poly(const string& path) {
 
         // Generate a new Shape for the poly
         TGShape     shape;
-        TGSuperPoly sp;
-
+        tgPolygon   poly;
+        SGGeod      p;
+        
         for (k=0; k<num_polys;k++) {
 
             if ( with_tp ) {
-                double width, length;
-                double heading;
-                double minu, maxu;
-                double minv, maxv;
-
                 in >> x;
                 in >> y;
-                in >> width;
-                in >> length;
-                in >> heading;
-                in >> minu;
-                in >> maxu;
-                in >> minv;
-                in >> maxv;
+                tp.ref    = SGGeod::fromDeg(x,y);
 
-                tp.set_ref( SGGeod::fromDeg(x,y) );
-                tp.set_width( width );
-                tp.set_length( length );
-                tp.set_heading( heading );
-                tp.set_minu( minu );
-                tp.set_maxu( maxu );
-                tp.set_minv( minv );
-                tp.set_maxv( maxv );
+                in >> tp.width;
+                in >> tp.length;
+                in >> tp.heading;
+                in >> tp.minu;
+                in >> tp.maxu;
+                in >> tp.minv;
+                in >> tp.maxv;
+                poly.SetTexParams( tp );
             }
 
             in >> contours;
 
-            poly.erase();
-
+            poly.Erase();
             for ( i = 0; i < contours; ++i ) {
                 in >> count;
 
@@ -172,14 +156,13 @@ bool TGConstruct::load_poly(const string& path) {
                     startz = -9999.0;
                 }
 
-                p = Point3D(startx+nudge, starty+nudge, startz);
-                p.snap( gSnap );
-                poly.add_node( i, p );
+                p = SGGeod::fromDegM(startx+nudge, starty+nudge, startz );
+                poly.AddNode( i, p );
 
                 if ( poly3d ) {
-                    nodes.unique_add_fixed_elevation( p.toSGGeod() );
+                    nodes.unique_add_fixed_elevation( p );
                 } else {
-                    nodes.unique_add( p.toSGGeod() );
+                    nodes.unique_add( p );
                 }
 
                 for ( j = 1; j < count - 1; ++j ) {
@@ -190,13 +173,14 @@ bool TGConstruct::load_poly(const string& path) {
                     } else {
                         z = -9999.0;
                     }
-                    p = Point3D( x+nudge, y+nudge, z );
-                    p.snap( gSnap );
-                    poly.add_node( i, p );
+
+                    p = SGGeod::fromDegM( x+nudge, y+nudge, z );
+                    poly.AddNode( i, p );
+
                     if ( poly3d ) {
-                        nodes.unique_add_fixed_elevation( p.toSGGeod() );
+                        nodes.unique_add_fixed_elevation( p );
                     } else {
-                        nodes.unique_add( p.toSGGeod() );
+                        nodes.unique_add( p );
                     }
                 }
 
@@ -213,31 +197,27 @@ bool TGConstruct::load_poly(const string& path) {
                      (fabs(startz - lastz) < SG_EPSILON) ) {
                     // last point same as first, discard
                 } else {
-                    p = Point3D( lastx+nudge, lasty+nudge, lastz );
-                    p.snap( gSnap );
-                    poly.add_node( i, p );
+                    p = SGGeod::fromDegM( lastx+nudge, lasty+nudge, lastz );
+                    poly.AddNode( i, p );
+
                     if ( poly3d ) {
-                        nodes.unique_add_fixed_elevation( p.toSGGeod() );
+                        nodes.unique_add_fixed_elevation( p );
                     } else {
-                        nodes.unique_add( p.toSGGeod() );
+                        nodes.unique_add( p );
                     }
                 }
             }
 
-            poly = remove_dups( poly );
-
-            sp.set_poly( poly );
-            sp.set_material( material );
-            shape.sps.push_back( sp );
+            poly = tgPolygon::Snap( poly, gSnap );
+            poly = tgPolygon::RemoveDups( poly );
+            poly.SetMaterial( material );
 
             if ( with_tp ) {
                 shape.textured = true;
-                shape.tps.push_back( tp );
-            }
-            else
-            {
+            } else {
                 shape.textured = false;
             }
+            shape.polys.push_back( poly );
 
             in >> skipcomment;
         }
@@ -250,7 +230,7 @@ bool TGConstruct::load_poly(const string& path) {
         polys_in.add_shape( area, shape );
 
         if ( IsDebugShape( shape.id ) ) {
-            WriteDebugShape( "loaded", shape );
+            tgPolygon::ToShapefile( shape.mask, ds_name, "loaded", "" );
         }
     }
 
diff --git a/src/BuildTiles/Main/tgconstruct_shared.cxx b/src/BuildTiles/Main/tgconstruct_shared.cxx
index ee591545..a5287b8e 100644
--- a/src/BuildTiles/Main/tgconstruct_shared.cxx
+++ b/src/BuildTiles/Main/tgconstruct_shared.cxx
@@ -128,22 +128,21 @@ void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt )
         unsigned int segment = faces[j].seg;
         unsigned int tri     = faces[j].tri;
 
-        int_list face_nodes = polys_clipped.get_tri_idxs( at, shape, segment ).get_contour( tri ) ;
-        {
-            SGGeod p1 = nodes.get_node( face_nodes[0] ).GetPosition();
-            SGGeod p2 = nodes.get_node( face_nodes[1] ).GetPosition();
-            SGGeod p3 = nodes.get_node( face_nodes[2] ).GetPosition();
+        tgPolygon poly = polys_clipped.get_poly( at, shape, segment );
 
-            SGVec3d wgs_p1 = nodes.get_node( face_nodes[0] ).GetWgs84();
-            SGVec3d wgs_p2 = nodes.get_node( face_nodes[1] ).GetWgs84();
-            SGVec3d wgs_p3 = nodes.get_node( face_nodes[2] ).GetWgs84();
+        SGGeod p1 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetPosition();
+        SGGeod p2 = nodes.get_node( poly.GetTriIdx( tri, 1) ).GetPosition();
+        SGGeod p3 = nodes.get_node( poly.GetTriIdx( tri, 2) ).GetPosition();
 
-            double  face_area   = triangle_area( p1, p2, p3 );
-            SGVec3d face_normal = calc_normal( face_area, wgs_p1, wgs_p2, wgs_p3 );
+        SGVec3d wgs_p1 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetWgs84();
+        SGVec3d wgs_p2 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetWgs84();
+        SGVec3d wgs_p3 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetWgs84();
 
-            sgWriteDouble( fp, face_area );
-            sgWritedVec3( fp, face_normal );
-        }
+        double  face_area   = triangle_area( p1, p2, p3 );
+        SGVec3f face_normal = calc_normal( face_area, wgs_p1, wgs_p2, wgs_p3 );
+
+        sgWriteDouble( fp, face_area );
+        sgWriteVec3( fp, face_normal );
     }
 }
 
@@ -180,20 +179,20 @@ void TGConstruct::ReadNeighborFaces( gzFile& fp )
 
     for (int i=0; i<count; i++) {
         TGNeighborFaces* pFaces;
-        Point3D          node;
+        SGGeod           node;
         int              num_faces;
 
-        sgReadPoint3D( fp, node );
+        sgReadGeod( fp, node );
 
         // look to see if we already have this node
         // If we do, (it's a corner) add more faces to it.
         // otherwise, initialize it with our elevation data
-        pFaces = FindNeighborFaces( node );
+        pFaces = FindNeighborFaces( Point3D::fromSGGeod( node ) );
         if ( !pFaces ) {
-            pFaces = AddNeighborFaces( node );
+            pFaces = AddNeighborFaces( Point3D::fromSGGeod( node ) );
 
             // new face - let's add our elevation first
-            int idx = nodes.find( node.toSGGeod() );
+            int idx = nodes.find( node );
             if (idx >= 0) {
                 TGNode local = nodes.get_node( idx );
                 pFaces->elevations.push_back( local.GetPosition().getElevationM() );
@@ -201,19 +200,19 @@ void TGConstruct::ReadNeighborFaces( gzFile& fp )
         }
 
         // remember all of the elevation data for the node, so we can average
-        pFaces->elevations.push_back( node.z() );
+        pFaces->elevations.push_back( node.getElevationM() );
 
         sgReadInt( fp, &num_faces );
         for (int j=0; j<num_faces; j++)
         {
             double  area;
-            Point3D normal;
+            SGVec3f normal;
 
             sgReadDouble( fp, &area );
             pFaces->face_areas.push_back( area );
 
-            sgReadPoint3D( fp, normal );
-            pFaces->face_normals.push_back( normal );
+            sgReadVec3( fp, normal );
+            pFaces->face_normals.push_back( Point3D::fromSGVec3( normal ) );
         }
     }
 }
diff --git a/src/BuildTiles/Main/tgconstruct_tesselate.cxx b/src/BuildTiles/Main/tgconstruct_tesselate.cxx
index 676f0da5..99df3b46 100644
--- a/src/BuildTiles/Main/tgconstruct_tesselate.cxx
+++ b/src/BuildTiles/Main/tgconstruct_tesselate.cxx
@@ -46,14 +46,14 @@ 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) );
+                tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "preteselate", "" );
             }
 
             for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
-                TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
+                tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
 
-                poly.get_bounding_box(min, max);
-                nodes.get_geod_inside( min, max, poly_extra );
+                tg::Rectangle rect = poly.GetBoundingBox();
+                nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra );
 
                 SG_LOG( SG_CLIPPER, SG_INFO, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
                         shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) <<
@@ -63,18 +63,17 @@ void TGConstruct::TesselatePolys( void )
                     SG_LOG( SG_CLIPPER, SG_INFO, poly );
                 }
 
-                TGPolygon tri = polygon_tesselate_alt_with_extra_cgal( poly, poly_extra, false );
+                poly.Tesselate( poly_extra );
 
                 // ensure all added nodes are accounted for
-                for (int k=0; k< tri.contours(); k++) {
-                    for (int l = 0; l < tri.contour_size(k); l++) {
+                for (unsigned int k=0; k < poly.Triangles(); k++) {
+                    for (int l = 0; l < 3; l++) {
                         // ensure we have all nodes...
-                        nodes.unique_add( tri.get_pt( k, l ).toSGGeod() );
+                        nodes.unique_add( poly.GetTriNode( k, l ) );
                     }
                 }
 
-                // Save the triangulation
-                polys_clipped.set_tris( area, shape, segment, tri );
+                polys_clipped.set_poly( area, shape, segment, poly );
             }
         }
     }
diff --git a/src/BuildTiles/Main/tgconstruct_texture.cxx b/src/BuildTiles/Main/tgconstruct_texture.cxx
index 1f20fd59..19cb7842 100644
--- a/src/BuildTiles/Main/tgconstruct_texture.cxx
+++ b/src/BuildTiles/Main/tgconstruct_texture.cxx
@@ -166,21 +166,19 @@ void TGConstruct::CalcTextureCoordinates( void )
     for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
         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++ ) {
-                TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
+                tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
                 SG_LOG( SG_CLIPPER, SG_INFO, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
-                        shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
-
-                TGPolygon tri = polys_clipped.get_tris( area, shape, segment );
-                TGPolygon tc;
+                        shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() );
 
                 if ( polys_clipped.get_textured( area, shape ) ) {
                     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) );
+                    poly.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, -1, -1, 1, 1 );
                 } else {
                     SG_LOG(SG_GENERAL, SG_DEBUG, "USE SIMGEAR for tex coord calculations" );
-                    tc = area_tex_coords( tri );
+                    poly.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() );
                 }
-                polys_clipped.set_texcoords( area, shape, segment, tc );
+                poly.Texture( );
+                polys_clipped.set_poly(area, shape, segment, poly);
             }
         }
     }
diff --git a/src/BuildTiles/Main/tglandclass.hxx b/src/BuildTiles/Main/tglandclass.hxx
index 01f9c118..a1f812ff 100644
--- a/src/BuildTiles/Main/tglandclass.hxx
+++ b/src/BuildTiles/Main/tglandclass.hxx
@@ -50,7 +50,7 @@ public:
     }
     inline unsigned int shape_size( unsigned int area, unsigned int shape )
     {
-        return shapes[area][shape].sps.size();
+        return shapes[area][shape].polys.size();
     }
 
     inline void add_shape( unsigned int area, TGShape shape )
@@ -62,13 +62,13 @@ public:
         return shapes[area][shape];
     }
 
-    inline TGPolygon get_mask( unsigned int area, unsigned int shape )
+    inline tgPolygon get_mask( unsigned int area, unsigned int shape )
     {
-        return shapes[area][shape].clip_mask;
+        return shapes[area][shape].mask;
     }
-    inline void set_mask( unsigned int area, unsigned int shape, TGPolygon mask )
+    inline void set_mask( unsigned int area, unsigned int shape, tgPolygon mask )
     {
-        shapes[area][shape].clip_mask = mask;
+        shapes[area][shape].mask = mask;
     }
 
     inline bool get_textured( unsigned int area, unsigned int shape )
@@ -80,24 +80,16 @@ public:
         shapes[area][shape].textured = t;
     }
 
-    inline TGSuperPoly& get_superpoly( unsigned int area, unsigned int shape, unsigned int segment )
+    inline tgPolygon& get_poly( unsigned int area, unsigned int shape, unsigned int segment )
     {
-        return shapes[area][shape].sps[segment];
+        return shapes[area][shape].polys[segment];
     }
-    inline void set_superpoly( unsigned int area, unsigned int shape, unsigned int segment, TGSuperPoly sp )
+    inline void set_poly( unsigned int area, unsigned int shape, unsigned int segment, const tgPolygon& sp )
     {
-        shapes[area][shape].sps[segment] = sp;
-    }
-
-    inline TGPolygon get_poly( unsigned int area, unsigned int shape, unsigned int segment )
-    {
-        return shapes[area][shape].sps[segment].get_poly();
-    }
-    inline void set_poly( unsigned int area, unsigned int shape, unsigned int segment, TGPolygon poly )
-    {
-        return shapes[area][shape].sps[segment].set_poly( poly );
+        shapes[area][shape].polys[segment] = sp;
     }
 
+#if 0
     inline TGPolygon get_tris( unsigned int area, unsigned int shape, unsigned int segment )
     {
         return shapes[area][shape].sps[segment].get_tris();
@@ -106,32 +98,35 @@ public:
     {
         shapes[area][shape].sps[segment].set_tris( tris );
     }
+#endif
 
     inline Point3D get_face_normal( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri )
     {
-        return shapes[area][shape].sps[segment].get_face_normal( tri );
+        return Point3D::fromSGVec3( shapes[area][shape].polys[segment].GetTriFaceNormal( tri ) );
     }
 
     inline double get_face_area( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri )
     {
-        return shapes[area][shape].sps[segment].get_face_area( tri );
+        return shapes[area][shape].polys[segment].GetTriFaceArea( tri );
     }
 
+#if 0
     inline std::string get_flag( unsigned int area, unsigned int shape, unsigned int segment )
     {
         return shapes[area][shape].sps[segment].get_flag();
     }
+#endif
 
     inline std::string get_material( unsigned int area, unsigned int shape, unsigned int segment )
     {
-        return shapes[area][shape].sps[segment].get_material();
+        return shapes[area][shape].polys[segment].GetMaterial();
     }
-    inline TGTexParams& get_texparams( unsigned int area, unsigned int shape, unsigned int segment )
+    inline const tgTexParams& get_texparams( unsigned int area, unsigned int shape, unsigned int segment )
     {
-        return shapes[area][shape].tps[segment];
+        return shapes[area][shape].polys[segment].GetTexParams();
     }
 
-
+/*
     inline TGPolygon get_texcoords( unsigned int area, unsigned int shape, unsigned int segment )
     {
         return shapes[area][shape].sps[segment].get_texcoords();
@@ -140,7 +135,9 @@ public:
     {
         return shapes[area][shape].sps[segment].set_texcoords( tcs );
     }
+*/
 
+/*
     inline TGPolyNodes get_tri_idxs( unsigned int area, unsigned int shape, unsigned int segment )
     {
         return shapes[area][shape].sps[segment].get_tri_idxs();
@@ -149,6 +146,8 @@ public:
     {
         return shapes[area][shape].sps[segment].set_tri_idxs( tis );
     }
+*/
+
     void SaveToGzFile( gzFile& fp );
     void LoadFromGzFile( gzFile& fp );
 
diff --git a/src/BuildTiles/Main/tgshape.cxx b/src/BuildTiles/Main/tgshape.cxx
index 540dadd9..54e1ec72 100644
--- a/src/BuildTiles/Main/tgshape.cxx
+++ b/src/BuildTiles/Main/tgshape.cxx
@@ -35,92 +35,69 @@ void TGShape::GetName( char* name ) const
     sprintf( name, "%s_%d", get_area_name( (AreaType)area ).c_str(), id );
 }
 
-void TGShape::SetMask( TGPolygon mask )
+void TGShape::SetMask( const tgPolygon& m )
 {
-    clip_mask = mask;
+    mask = m;
 }
 
 void TGShape::BuildMask( void )
 {
-    TGPolygon poly;
-    poly_list polys;
-    clip_mask.erase();
-
-    for (unsigned int i=0; i<sps.size(); i++)
-    {
-        polys.push_back( sps[i].get_poly() );
-    }
-
-    clip_mask = tgPolygonUnion( polys );
+    mask = tgPolygon::Union( polys );
 }
 
 void TGShape::IntersectPolys( void )
 {
-    if ( sps.size() > 1 ) {
-        TGPolygon original, intersect;
-
-        for (unsigned int i=0; i<sps.size(); i++)
+    if ( polys.size() > 1 ) {
+        for (unsigned int i=0; i<polys.size(); i++)
         {
-            original  = sps[i].get_poly();
-
-            intersect = tgPolygonInt( clip_mask, original );
-
-            sps[i].set_poly( intersect );
+            SG_LOG(SG_GENERAL, SG_INFO, " before is " << polys[i].GetMaterial() );
+            polys[i] = tgPolygon::Intersect( polys[i], mask );
+            SG_LOG(SG_GENERAL, SG_INFO, " after is " << polys[i].GetMaterial() );
         }
     } else {
-        sps[0].set_poly( clip_mask );
+        std::string material = polys[0].GetMaterial();
+        tgTexParams tp = polys[0].GetTexParams();
+        polys[0] = mask;
+        polys[0].SetMaterial( material );
+        polys[0].SetTexParams( tp );
     }
 }
 
 void TGShape::LoadFromGzFile(gzFile& fp)
 {
     int i, count;
+
     // First, load the clipmask
-    clip_mask.LoadFromGzFile( fp );
+    SG_LOG(SG_GENERAL, SG_INFO, " load mask" );
+    mask.LoadFromGzFile( fp );
+    SG_LOG(SG_GENERAL, SG_INFO, " done" );
 
-    // Then load superpolys
+    // Then load individual polys
     sgReadInt( fp, &count );
     for (i=0; i<count; i++) {
-    TGSuperPoly sp;
-        sp.LoadFromGzFile( fp );
-        sps.push_back( sp );
-    }
-
-    // Then load texparams
-    sgReadInt( fp, &count );
-    for (i=0; i<count; i++) {
-    TGTexParams tp;
-        tp.LoadFromGzFile( fp );
-        tps.push_back( tp );
+        tgPolygon poly;
+        poly.LoadFromGzFile( fp );
+        polys.push_back( poly );
     }
 
     // Load the id, area type and textured flag
     sgReadUInt( fp, &id );
-    sgReadInt( fp, (int*)&area );
-    sgReadInt( fp, (int*)&textured );
+    sgReadInt(  fp, (int*)&area );
+    sgReadInt(  fp, (int*)&textured );
 }
 
 std::ostream& operator<< ( std::ostream& out, const TGShape& p )
 {
     int i, count;
-//    TGSuperPoly sp;
-//    TGTexParams tp;
 
     // First, save the clipmask
-    out << p.clip_mask;
+    out << p.mask;
 
     // Then save superpolys
-    count = p.sps.size();
+    count = p.polys.size();
     out << count << "\n";
     for (i=0; i<count; i++) {
-        out << p.sps[i];
-    }
-
-    // Then save texparams
-    count = p.tps.size();
-    out << count << "\n";
-    for (i=0; i<count; i++) {
-        out << p.tps[i];
+        out << p.polys[i];
     }
 
     // Save the id, area type and textured flag
@@ -135,21 +112,14 @@ void TGShape::SaveToGzFile(gzFile& fp)
 {
     int i, count;
 
-    // First, load the clipmask
-    clip_mask.SaveToGzFile( fp );
+    // First, save the clipmask
+    mask.SaveToGzFile( fp );
 
     // Then save superpolys
-    count = sps.size();
+    count = polys.size();
     sgWriteInt( fp, count );
     for (i=0; i<count; i++) {
-        sps[i].SaveToGzFile( fp );
-    }
-
-    // Then save texparams
-    count = tps.size();
-    sgWriteInt( fp, count );
-    for (i=0; i<count; i++) {
-        tps[i].SaveToGzFile( fp );
+        polys[i].SaveToGzFile( fp );
     }
 
     // Save the id, area type and textured flag
diff --git a/src/BuildTiles/Main/tgshape.hxx b/src/BuildTiles/Main/tgshape.hxx
index 17e6f0cc..dc15e9b3 100644
--- a/src/BuildTiles/Main/tgshape.hxx
+++ b/src/BuildTiles/Main/tgshape.hxx
@@ -45,15 +45,14 @@
 class TGShape
 {
 public:
-    TGPolygon       clip_mask;
+    tgpolygon_list  polys;
+    tgPolygon       mask;
     bool            textured;
-    superpoly_list  sps;
-    texparams_list  tps;
     AreaType        area;
     unsigned int    id;
 
     void GetName( char* name ) const;
-    void SetMask( TGPolygon mask );
+    void SetMask( const tgPolygon& mask );
     void BuildMask( void );
     void IntersectPolys( void );
     void SaveToGzFile( gzFile& fp );
diff --git a/src/Lib/Polygon/polygon.cxx b/src/Lib/Polygon/polygon.cxx
index 2190fc7b..31d8ec0f 100644
--- a/src/Lib/Polygon/polygon.cxx
+++ b/src/Lib/Polygon/polygon.cxx
@@ -23,14 +23,15 @@
 #include <fstream>
 #include <limits.h>
 
+#include <simgear/constants.h>
 #include <simgear/threads/SGThread.hxx>
 #include <simgear/threads/SGGuard.hxx>
-#include <simgear/constants.h>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/misc/texcoord.hxx>
+#include <simgear/structure/exception.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <Geometry/point3d.hxx>
 #include <Geometry/poly_support.hxx>
-#include <simgear/math/sg_geodesy.hxx>
-#include <simgear/structure/exception.hxx>
 
 #include <Geometry/trinodes.hxx>
 
@@ -1962,6 +1963,36 @@ bool tgContour::FindColinearLine( const tgContour& subject, const SGGeod& node,
     return false;
 }
 
+void tgContour::SaveToGzFile( gzFile& fp )
+{
+    // Save the nodelist
+    sgWriteUInt( fp, node_list.size() );
+    for (unsigned int i = 0; i < node_list.size(); i++) {
+        sgWriteGeod( fp, node_list[i] );
+    }
+
+    // and the hole flag
+    sgWriteInt( fp, (int)hole );
+}
+
+void tgContour::LoadFromGzFile( gzFile& fp )
+{
+    unsigned int count;
+    SGGeod node;
+
+    // Start Clean
+    Erase();
+
+    // Load the nodelist
+    sgReadUInt( fp, &count );
+    for (unsigned int i = 0; i < count; i++) {
+        sgReadGeod( fp, node );
+        node_list.push_back( node );
+    }
+
+    sgReadInt( fp, (int *)&hole );
+}
+
 std::ostream& operator<< ( std::ostream& output, const tgContour& subject )
 {
     // Save the data
@@ -2429,10 +2460,11 @@ void tgPolygon::RemoveSlivers( tgPolygon& subject, tgcontour_list& slivers )
 #endif
 }
 
-void tgPolygon::MergeSlivers( tgpolygon_list& polys, tgcontour_list& sliver_list ) {
+tgcontour_list tgPolygon::MergeSlivers( tgpolygon_list& polys, tgcontour_list& sliver_list ) {
     tgPolygon poly, result;
     tgContour sliver;
     tgContour contour;
+    tgcontour_list unmerged;
     unsigned int original_contours, result_contours;
     bool done;
 
@@ -2462,8 +2494,11 @@ void tgPolygon::MergeSlivers( tgpolygon_list& polys, tgcontour_list& sliver_list
 
         if ( !done ) {
             SG_LOG(SG_GENERAL, SG_DEBUG, "couldn't merge sliver " << i );
+            unmerged.push_back( sliver );
         }
     }
+
+    return unmerged;
 }
 
 tgPolygon tgPolygon::AddColinearNodes( const tgPolygon& subject, TGTriNodes& nodes )
@@ -2561,12 +2596,31 @@ void tgPolygon::Texture( void )
 
     switch( tp.method ) {
         case TG_TEX_BY_GEODE:
-            break;
+        {
+            // The Simgear General texture coordinate routine takes a fan.
+            // Simgear could probably use a new function that just takes a Geod vector
+            // For now, just create an identity fan...
+            std::vector< int > node_idxs;
+            for (int i = 0; i < 3; i++) {
+                node_idxs.push_back(i);
+            }
+
+            for ( unsigned int i = 0; i < triangles.size(); i++ ) {
+                std::vector< SGVec2f > tc_list;
+                std::vector< SGGeod > nodes;
+
+                nodes = triangles[i].GetNodeList();
+                tc_list = sgCalcTexCoords( tp.center_lat, nodes, node_idxs );
+                triangles[i].SetTexCoordList( tc_list );
+            }
+        }
+        break;
 
         case TG_TEX_BY_TPS_NOCLIP:
         case TG_TEX_BY_TPS_CLIPU:
         case TG_TEX_BY_TPS_CLIPV:
         case TG_TEX_BY_TPS_CLIPUV:
+        {
             for ( unsigned int i = 0; i < triangles.size(); i++ ) {
                 for ( unsigned int j = 0; j < 3; j++ ) {
                     p = triangles[i].GetNode( j );
@@ -2631,8 +2685,8 @@ void tgPolygon::Texture( void )
                     triangles[i].SetTexCoord( j, t );
                 }
             }
-
-            break;
+        }
+        break;
     }
 }
 
@@ -2691,6 +2745,82 @@ void tgPolygon::ToShapefile( const tgPolygon& subject, const std::string& dataso
     ds_id = tgShapefileCloseDatasource( ds_id );
 }
 
+    tgcontour_list  contours;
+    tgtriangle_list triangles;
+
+    std::string material;
+    std::string flag;       // let's get rid of this....
+    tgTexParams tp;
+
+
+void tgPolygon::SaveToGzFile( gzFile& fp )
+{
+    // Save the contours
+    sgWriteUInt( fp, contours.size() );
+    for (unsigned int i = 0; i < contours.size(); i++) {
+        contours[i].SaveToGzFile( fp );
+    }
+
+    // Save the triangles
+    sgWriteUInt( fp, triangles.size() );
+    for (unsigned int i = 0; i < triangles.size(); i++) {
+        triangles[i].SaveToGzFile( fp );
+    }
+
+    // Save the tex params
+    tp.SaveToGzFile( fp );
+
+    // and the rest
+    sgWriteString( fp, material.c_str() );
+    sgWriteString( fp, flag.c_str() );
+}
+
+void tgPolygon::LoadFromGzFile( gzFile& fp )
+{
+    unsigned int count;
+    tgContour contour;
+    tgTriangle triangle;
+    char *strbuff;
+
+    // Start clean
+    Erase();
+
+    // Load the contours
+    sgReadUInt( fp, &count );
+    for (unsigned int i = 0; i < count; i++) {
+        contour.LoadFromGzFile( fp );
+        AddContour(contour);
+    }
+
+    // load the triangles
+    sgReadUInt( fp, &count );
+    SG_LOG(SG_GENERAL, SG_INFO, " load " << count << " triangles" );
+
+    for (unsigned int i = 0; i < count; i++) {
+        triangle.LoadFromGzFile( fp );
+        AddTriangle(triangle);
+    }
+
+    SG_LOG(SG_GENERAL, SG_INFO, " load texparams" );
+
+    // Load the tex params
+    tp.LoadFromGzFile( fp );
+
+    // and the rest
+    SG_LOG(SG_GENERAL, SG_INFO, " load material" );
+
+    sgReadString( fp, &strbuff );
+    if ( strbuff ) {
+        material = strbuff;
+        delete strbuff;
+    }
+
+    sgReadString( fp, &strbuff );
+    if ( strbuff ) {
+        flag = strbuff;
+        delete strbuff;
+    }
+}
 
 ////////////////////////////// CHOP ////////////////////////////////
 #include <simgear/bucket/newbucket.hxx>
@@ -3058,7 +3188,7 @@ void tg_insert_polygon(CDT& cdt,const Polygon_2& polygon)
     }
 }
 
-void tgPolygon::Tesselate( std::vector<SGGeod> extra )
+void tgPolygon::Tesselate( const std::vector<SGGeod>& extra )
 {
     CDT       cdt;
 
@@ -3355,3 +3485,87 @@ void tgAccumulator::Add( const tgPolygon& subject )
     ClipperLib::Polygons clipper_subject = tgPolygon::ToClipper( subject );
     accum.push_back( clipper_subject );
 }
+
+    std::vector<SGGeod>  node_list;
+    std::vector<SGVec2f> tc_list;
+    std::vector<SGVec3d> norm_list;
+    std::vector<int>     idx_list;
+
+    SGVec3f face_normal;
+    double  face_area;
+
+
+void tgTriangle::SaveToGzFile( gzFile& fp )
+{
+    // Save the three nodes, and their attributes
+    for (unsigned int i = 0; i < 3; i++) {
+        sgWriteGeod( fp, node_list[i] );
+        sgWriteVec2( fp, tc_list[i] );
+        sgWritedVec3( fp, norm_list[i] );
+        sgWriteInt( fp, idx_list[i] );
+    }
+
+    // and the area, and face normal
+    sgWriteVec3( fp, face_normal );
+    sgWriteDouble( fp, face_area );
+}
+
+void tgTriangle::LoadFromGzFile( gzFile& fp )
+{
+    // Load the nodelist
+    for (unsigned int i = 0; i < 3; i++) {
+        sgReadGeod( fp, node_list[i] );
+        sgReadVec2( fp, tc_list[i] );
+        sgReaddVec3( fp, norm_list[i] );
+        sgReadInt( fp, &idx_list[i] );
+    }
+
+    // and the area, and face normal
+    sgReadVec3( fp, face_normal );
+    sgReadDouble( fp, &face_area );
+}
+
+void tgTexParams::SaveToGzFile( gzFile& fp )
+{
+    // Save the parameters
+    sgWriteGeod( fp, ref );
+
+    sgWriteDouble( fp, width );
+    sgWriteDouble( fp, length );
+    sgWriteDouble( fp, heading );
+
+    sgWriteDouble( fp, minu );
+    sgWriteDouble( fp, maxu );
+    sgWriteDouble( fp, minv );
+    sgWriteDouble( fp, maxv );
+
+    sgWriteDouble( fp, min_clipu );
+    sgWriteDouble( fp, max_clipu );
+    sgWriteDouble( fp, min_clipv );
+    sgWriteDouble( fp, max_clipv );
+
+    sgWriteInt( fp, (int)method );
+}
+
+void tgTexParams::LoadFromGzFile( gzFile& fp )
+{
+    // Load the parameters
+    sgReadGeod( fp, ref );
+
+    sgReadDouble( fp, &width );
+    sgReadDouble( fp, &length );
+    sgReadDouble( fp, &heading );
+
+    sgReadDouble( fp, &minu );
+    sgReadDouble( fp, &maxu );
+    sgReadDouble( fp, &minv );
+    sgReadDouble( fp, &maxv );
+
+    sgReadDouble( fp, &min_clipu );
+    sgReadDouble( fp, &max_clipu );
+    sgReadDouble( fp, &min_clipv );
+    sgReadDouble( fp, &max_clipv );
+
+    sgReadInt( fp, (int*)&method );
+}
+
diff --git a/src/Lib/Polygon/polygon.hxx b/src/Lib/Polygon/polygon.hxx
index b127ad6c..3d13eb1f 100644
--- a/src/Lib/Polygon/polygon.hxx
+++ b/src/Lib/Polygon/polygon.hxx
@@ -386,6 +386,11 @@ public:
 
     static tgContour Expand( const tgContour& subject, double offset );
 
+    static void ToShapefile( const tgContour& subject, const std::string& datasource, const std::string& layer, const std::string& feature );
+
+    void SaveToGzFile( gzFile& fp );
+    void LoadFromGzFile( gzFile& fp );
+
     // Friend for output
     friend std::ostream& operator<< ( std::ostream&, const tgContour& );
 
@@ -401,6 +406,13 @@ typedef tgcontour_list::const_iterator const_tgcontour_list_iterator;
 class tgTriangle
 {
 public:
+    tgTriangle() {
+        node_list.resize( 3, SGGeod::fromDegM(0.0, 0.0, 0.0) );
+        tc_list.resize(   3, SGVec2f(0.0, 0.0) );
+        norm_list.resize( 3, SGVec3d(0.0, 0.0, 0.0) );
+        idx_list.resize(  3, -1 );
+    }
+
     tgTriangle( const SGGeod& p0, const SGGeod& p1, const SGGeod& p2 ) {
         node_list.push_back( p0 );
         node_list.push_back( p1 );
@@ -414,12 +426,42 @@ public:
     SGGeod GetNode( unsigned int i ) const {
         return node_list[i];
     }
+    std::vector<SGGeod>& GetNodeList( void ) {
+        return node_list;
+    }
+
     SGVec2f GetTexCoord( unsigned int i ) const {
         return tc_list[i];
     }
     void SetTexCoord( unsigned int i, const SGVec2f tc ) {
         tc_list[i] = tc;
     }
+    void SetTexCoordList( const std::vector<SGVec2f>& tcs ) {
+        tc_list = tcs;
+    }
+    int GetIndex( unsigned int i ) const {
+        return idx_list[i];
+    }
+    void SetIndex( unsigned int i, int idx ) {
+        idx_list[i] = idx;
+    }
+
+    void    SetFaceNormal( const SGVec3f& n ) {
+        face_normal = n;
+    };
+    SGVec3f GetFaceNormal( void ) const {
+        return face_normal;
+    }
+
+    void    SetFaceArea( double a ) {
+        face_area = a;
+    }
+    double  GetFaceArea( void ) const {
+        return face_area;
+    }
+
+    void SaveToGzFile( gzFile& fp );
+    void LoadFromGzFile( gzFile& fp );
 
     // Friend for output
     friend std::ostream& operator<< ( std::ostream&, const tgTriangle& );
@@ -430,7 +472,7 @@ private:
     std::vector<SGVec3d> norm_list;
     std::vector<int>     idx_list;
 
-    SGVec3d face_normal;
+    SGVec3f face_normal;
     double  face_area;
 };
 
@@ -466,6 +508,11 @@ public:
 
     tgTexMethod method;
 
+    double center_lat;
+
+    void SaveToGzFile( gzFile& fp );
+    void LoadFromGzFile( gzFile& fp );
+
     // Friend for output
     friend std::ostream& operator<< ( std::ostream&, const tgTexParams& );
 };
@@ -531,6 +578,9 @@ public:
     unsigned int Triangles( void ) const {
         return triangles.size();
     }
+    void AddTriangle( const tgTriangle& triangle ) {
+        triangles.push_back( triangle );
+    }
     void AddTriangle( const SGGeod& p1, const SGGeod p2, const SGGeod p3 ) {
         triangles.push_back( tgTriangle( p1, p2, p3 ) );
     }
@@ -541,6 +591,24 @@ public:
     SGVec2f GetTriTexCoord( unsigned int c, unsigned int i ) const {
         return triangles[c].GetTexCoord( i );
     }
+    void SetTriIdx( unsigned int c, unsigned int i, int idx ) {
+        triangles[c].SetIndex( i, idx );
+    }
+    int GetTriIdx( unsigned int c, unsigned int i ) const {
+        return triangles[c].GetIndex( i );
+    }
+    void SetTriFaceNormal( unsigned int c, const SGVec3f& n ) {
+        triangles[c].SetFaceNormal( n );
+    }
+    SGVec3f GetTriFaceNormal( unsigned int c ) const {
+        return triangles[c].GetFaceNormal();
+    }
+    void SetTriFaceArea( unsigned int c, double a ) {
+        triangles[c].SetFaceArea( a );
+    }
+    double GetTriFaceArea( unsigned int c ) const {
+        return triangles[c].GetFaceArea();
+    }
 
     std::string GetMaterial( void ) const {
         return material;
@@ -560,7 +628,7 @@ public:
     const tgTexParams& GetTexParams( void ) const {
         return tp;
     }
-    
+
     void SetTexLimits( double minu, double minv, double maxu, double maxv ) {
         tp.minu = minu;
         tp.minv = minv;
@@ -577,9 +645,14 @@ public:
         tp.max_clipu = max_cu;
         tp.max_clipv = max_cv;
     }
+    void SetTexMethod( tgTexMethod m, double cl ) {
+        tp.method = m;
+        tp.center_lat = cl;
+    }
 
+    
     void Tesselate( void );
-    void Tesselate( std::vector<SGGeod> extra );
+    void Tesselate( const std::vector<SGGeod>& extra );
 
     void Texture( void );
 
@@ -623,7 +696,7 @@ public:
     static bool      FindColinearLine( const tgPolygon& subject, SGGeod& node, SGGeod& start, SGGeod& end );
 
     static void RemoveSlivers( tgPolygon& subject, tgcontour_list& slivers );
-    static void MergeSlivers( tgpolygon_list& subjects, tgcontour_list& slivers );
+    static tgcontour_list MergeSlivers( tgpolygon_list& subjects, tgcontour_list& slivers );
 
     void SaveToGzFile( gzFile& fp );
     void LoadFromGzFile( gzFile& fp );