1
0
Fork 0

refactor from TGPolygon and TGSuperPoly to tgPolygon

fix for missing texture coordinates.  Need to kill, or shrink TGShape / clip ,asks, etc.
This commit is contained in:
Peter Sadrozinski 2012-12-02 11:01:31 -05:00
parent c0555a1270
commit 89e69a863f
18 changed files with 624 additions and 466 deletions

View file

@ -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 );

View file

@ -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

View file

@ -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 ) );
}
}
}

View file

@ -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

View file

@ -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 );

View file

@ -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;
}

View file

@ -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 );
}
}
}

View file

@ -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

View file

@ -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 );

View file

@ -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", "" );
}
}

View file

@ -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 ) );
}
}
}

View file

@ -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 );
}
}
}

View file

@ -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);
}
}
}

View file

@ -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 );

View file

@ -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

View file

@ -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 );

View file

@ -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 );
}

View file

@ -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 );