1
0
Fork 0

- fixed multithreaded construct memory leak in TGArray usage ( need to clear corner and fitted lists ).

- reworked priorities.hxx/.cxx to make valgrind happy.  It also allows us to add more features per area (like smoothing).
- remove TG_MAX_AREA_TYPES - we had a merge request for this, but this does essentially the same thing with the refactoring.
- fixed some edge matching introduced in multithreaded construct.
- tgconstruct objects now live for an entire stage.  1 for each thread - this introduced the memory leaks, and some issues.
  interesting side effect is that we do less alloc / free, since we use std::vectors which when cleared, don't actually free
  memory, so by the end, we've allocated enough entries for the largest tile.
- fixed linear feature issue in genapts850 - the refactor caused some of the old clean functions to remove too many polys!
  with cgal, we need far less cleaning - just do what construct does, and we can still parse all airports, and lines are back.
This commit is contained in:
Peter Sadrozinski 2012-12-29 21:05:39 -05:00
parent b007979a38
commit 5b9375f102
35 changed files with 435 additions and 399 deletions

View file

@ -347,6 +347,8 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
features[i]->BuildBtg( line_polys, rwy_lights, lf_accum, make_shapefiles ); features[i]->BuildBtg( line_polys, rwy_lights, lf_accum, make_shapefiles );
} }
// lf_accum.ToShapefiles( "./lf_accum", "test", false );
log_time = time(0); log_time = time(0);
GENAPT_LOG( SG_GENERAL, SG_ALERT, "Finished building Linear Features for " << icao << " at " << DebugTimeToString(log_time) ); GENAPT_LOG( SG_GENERAL, SG_ALERT, "Finished building Linear Features for " << icao << " at " << DebugTimeToString(log_time) );
} }
@ -658,15 +660,18 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
{ {
tgPolygon poly = line_polys[k]; tgPolygon poly = line_polys[k];
#if 1
poly = tgPolygon::RemoveCycles( poly ); poly = tgPolygon::RemoveCycles( poly );
poly = tgPolygon::RemoveDups( poly ); poly = tgPolygon::RemoveDups( poly );
poly = tgPolygon::RemoveBadContours( poly ); poly = tgPolygon::RemoveBadContours( poly );
poly = tgPolygon::Simplify( poly );
poly = tgPolygon::RemoveTinyContours( poly ); // poly = tgPolygon::Simplify( poly );
poly = tgPolygon::RemoveSpikes( poly ); // poly = tgPolygon::RemoveTinyContours( poly );
poly = tgPolygon::RemoveDups( poly ); // poly = tgPolygon::RemoveSpikes( poly );
poly = tgPolygon::RemoveBadContours( poly ); // poly = tgPolygon::RemoveDups( poly );
poly = tgPolygon::RemoveTinyContours( poly ); // poly = tgPolygon::RemoveBadContours( poly );
// poly = tgPolygon::RemoveTinyContours( poly );
#endif
line_polys[k] = poly; line_polys[k] = poly;
} }
@ -1232,6 +1237,5 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
chopper.Add( divided_base, "Hole" ); chopper.Add( divided_base, "Hole" );
chopper.Add( apt_clearing, "Airport" ); chopper.Add( apt_clearing, "Airport" );
chopper.Save(); chopper.Save();
} }

View file

@ -457,7 +457,7 @@ int ClosedPoly::BuildBtg( tgpolygon_list& rwy_polys, tgcontour_list& slivers, tg
{ {
if( shapefile_name.size() ) { if( shapefile_name.size() ) {
tgShapefile::FromPolygon( pre_tess, "./airport_dbg", std::string("preclip"), shapefile_name ); tgShapefile::FromPolygon( pre_tess, "./airport_dbg", std::string("preclip"), shapefile_name );
accum.ToShapefiles( "./airport_dbg", "accum" ); accum.ToShapefiles( "./airport_dbg", "accum", true );
} }
tgPolygon clipped = accum.Diff( pre_tess ); tgPolygon clipped = accum.Diff( pre_tess );

View file

@ -362,110 +362,6 @@ LinearFeature::~LinearFeature()
} }
} }
#if 0
SGGeod LinearFeature::OffsetPointMiddle( const SGGeod& gPrev, const SGGeod& gCur, const SGGeod& gNext, double offset_by )
{
double courseCur, courseNext, courseAvg, theta;
SGVec3d dirCur, dirNext, dirAvg, cp;
double courseOffset, distOffset;
SGGeod pt;
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "Find average angle for contour: prev (" << gPrev << "), "
"cur (" << gCur << "), "
"next (" << gNext << ")" );
// first, find if the line turns left or right ar src
// for this, take the cross product of the vectors from prev to src, and src to next.
// if the cross product is negetive, we've turned to the left
// if the cross product is positive, we've turned to the right
courseCur = SGGeodesy::courseDeg( gCur, gPrev );
dirCur = SGVec3d( sin( courseCur*SGD_DEGREES_TO_RADIANS ), cos( courseCur*SGD_DEGREES_TO_RADIANS ), 0.0f );
courseNext = SGGeodesy::courseDeg( gCur, gNext );
dirNext = SGVec3d( sin( courseNext*SGD_DEGREES_TO_RADIANS ), cos( courseNext*SGD_DEGREES_TO_RADIANS ), 0.0f );
// Now find the average
dirAvg = normalize( dirCur + dirNext );
courseAvg = SGMiscd::rad2deg( atan( dirAvg.x()/dirAvg.y() ) );
if (courseAvg < 0) {
courseAvg += 180.0f;
}
// check the turn direction
cp = cross( dirCur, dirNext );
theta = SGMiscd::rad2deg(CalculateTheta( dirCur, dirNext, cp ) );
if ( (abs(theta - 180.0) < 0.1) || (abs(theta) < 0.1) || (isnan(theta)) ) {
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature: (degenerate case) " << description << ": theta is " << theta );
// straight line blows up math - offset 90 degree and dist is as given
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseNext-90.0);
distOffset = offset_by;
} else {
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature: (normal case) " << description << ": theta is " << theta );
// calculate correct distance for the offset point
if (cp.z() < 0.0f) {
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseAvg+180);
} else {
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseAvg);
}
distOffset = (offset_by)/sin(SGMiscd::deg2rad(courseNext-courseOffset));
}
// calculate the point from cur
pt = SGGeodesy::direct(gCur, courseOffset, distOffset);
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "\theading is " << courseOffset << " distance is " << distOffset << " point is (" << pt.getLatitudeDeg() << "," << pt.getLongitudeDeg() << ")" );
return pt;
}
SGGeod LinearFeature::OffsetPointFirst( const SGGeod& cur, const SGGeod& next, double offset_by )
{
double courseOffset;
SGGeod pt;
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "Find OffsetPoint at Start : cur (" << cur << "), "
"next (" << next << ")" );
// find the offset angle
courseOffset = SGGeodesy::courseDeg( cur, next ) - 90;
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseOffset);
// calculate the point from cur
pt = SGGeodesy::direct( cur, courseOffset, offset_by );
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "\theading is " << courseOffset << " distance is " << offset_by << " point is (" << pt.getLatitudeDeg() << "," << pt.getLongitudeDeg() << ")" );
return pt;
}
SGGeod LinearFeature::OffsetPointLast( const SGGeod& prev, const SGGeod& cur, double offset_by )
{
double courseOffset;
SGGeod pt;
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "Find OffsetPoint at End : prev (" << prev << "), "
"cur (" << cur << ")" );
// find the offset angle
courseOffset = SGGeodesy::courseDeg( prev, cur ) - 90;
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseOffset);
// calculate the point from cur
pt = SGGeodesy::direct( cur, courseOffset, offset_by );
GENAPT_LOG(SG_GENERAL, SG_DEBUG, "\theading is " << courseOffset << " distance is " << offset_by << " point is (" << pt.getLatitudeDeg() << "," << pt.getLongitudeDeg() << ")" );
return pt;
}
SGGeod midpoint( const SGGeod& p0, const SGGeod& p1 )
{
return SGGeod::fromDegM( (p0.getLongitudeDeg() + p1.getLongitudeDeg()) / 2,
(p0.getLatitudeDeg() + p1.getLatitudeDeg()) / 2,
(p0.getElevationM() + p1.getElevationM()) / 2 );
}
#endif
int LinearFeature::Finish( bool closed, unsigned int idx ) int LinearFeature::Finish( bool closed, unsigned int idx )
{ {
tgPolygon poly; tgPolygon poly;

View file

@ -97,10 +97,6 @@ public:
int BuildBtg( tgpolygon_list& line_polys, tglightcontour_list& lights, tgAccumulator& accum, bool debug ); int BuildBtg( tgpolygon_list& line_polys, tglightcontour_list& lights, tgAccumulator& accum, bool debug );
private: private:
// SGGeod OffsetPointFirst( const SGGeod& cur, const SGGeod& next, double offset_by );
// SGGeod OffsetPointMiddle( const SGGeod& prev, const SGGeod& cur, const SGGeod& next, double offset_by );
// SGGeod OffsetPointLast( const SGGeod& prev, const SGGeod& cur, double offset_by );
double offset; double offset;
double width; double width;
@ -128,4 +124,3 @@ private:
typedef std::vector <LinearFeature *> FeatureList; typedef std::vector <LinearFeature *> FeatureList;
#endif #endif

View file

@ -138,7 +138,7 @@ int Taxiway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_light
taxi_poly.AddContour( taxi_contour ); taxi_poly.AddContour( taxi_contour );
tgShapefile::FromPolygon( taxi_poly, "./airport_dbg", std::string("preclip"), shapefile_name ); tgShapefile::FromPolygon( taxi_poly, "./airport_dbg", std::string("preclip"), shapefile_name );
accum.ToShapefiles( "./airport_dbg", "accum" ); accum.ToShapefiles( "./airport_dbg", "accum", true );
} }
tgPolygon clipped = accum.Diff( taxi_contour ); tgPolygon clipped = accum.Diff( taxi_contour );

View file

@ -22,10 +22,13 @@
# include <config.h> # include <config.h>
#endif #endif
#include <boost/thread.hpp>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <Include/version.h> #include <Include/version.h>
#include "tgconstruct.hxx" #include "tgconstruct.hxx"
#include "priorities.hxx"
#include "usgs.hxx" #include "usgs.hxx"
using std::string; using std::string;
@ -47,6 +50,8 @@ static void usage( const string name ) {
SG_LOG(SG_GENERAL, SG_ALERT, " --priorities=<filename>"); SG_LOG(SG_GENERAL, SG_ALERT, " --priorities=<filename>");
SG_LOG(SG_GENERAL, SG_ALERT, " --usgs-map=<filename>"); SG_LOG(SG_GENERAL, SG_ALERT, " --usgs-map=<filename>");
SG_LOG(SG_GENERAL, SG_ALERT, " --ignore-landmass"); SG_LOG(SG_GENERAL, SG_ALERT, " --ignore-landmass");
SG_LOG(SG_GENERAL, SG_ALERT, " --threads");
SG_LOG(SG_GENERAL, SG_ALERT, " --threads=<numthreads>");
SG_LOG(SG_GENERAL, SG_ALERT, " ] <load directory...>"); SG_LOG(SG_GENERAL, SG_ALERT, " ] <load directory...>");
exit(-1); exit(-1);
} }
@ -60,6 +65,7 @@ int main(int argc, char **argv) {
string usgs_map_file = DEFAULT_USGS_MAPFILE; string usgs_map_file = DEFAULT_USGS_MAPFILE;
SGGeod min, max; SGGeod min, max;
long tile_id = -1; long tile_id = -1;
int num_threads = 1;
vector<string> load_dirs; vector<string> load_dirs;
bool ignoreLandmass = false; bool ignoreLandmass = false;
@ -104,6 +110,10 @@ int main(int argc, char **argv) {
usgs_map_file = arg.substr(11); usgs_map_file = arg.substr(11);
} else if (arg.find("--ignore-landmass") == 0) { } else if (arg.find("--ignore-landmass") == 0) {
ignoreLandmass = true; ignoreLandmass = true;
} else if (arg.find("--threads=") == 0) {
num_threads = atoi( arg.substr(10).c_str() );
} else if (arg.find("--threads") == 0) {
num_threads = boost::thread::hardware_concurrency();
} else if (arg.find("--debug-dir=") == 0) { } else if (arg.find("--debug-dir=") == 0) {
debug_dir = arg.substr(12); debug_dir = arg.substr(12);
} else if (arg.find("--debug-areas=") == 0) { } else if (arg.find("--debug-areas=") == 0) {
@ -117,8 +127,6 @@ int main(int argc, char **argv) {
} }
} }
int num_threads = 8;
if ( share_dir == "" ) { if ( share_dir == "" ) {
share_dir = work_dir + "/Shared"; share_dir = work_dir + "/Shared";
} }
@ -146,9 +154,9 @@ int main(int argc, char **argv) {
SG_LOG(SG_GENERAL, SG_ALERT, "Load directory: " << argv[i]); SG_LOG(SG_GENERAL, SG_ALERT, "Load directory: " << argv[i]);
} }
if ( !load_area_types( priorities_file ) TGAreaDefinitions areas;
|| (!cover.empty() && !load_usgs_map( usgs_map_file)) ) { if ( areas.init( priorities_file ) ) {
exit(-1); exit( -1 );
} }
// three identical work queues // three identical work queues
@ -195,8 +203,8 @@ int main(int argc, char **argv) {
std::vector<TGConstruct *> constructs; std::vector<TGConstruct *> constructs;
for (int i=0; i<num_threads; i++) { for (int i=0; i<num_threads; i++) {
TGConstruct* construct = new TGConstruct( 1, wq[0] ); TGConstruct* construct = new TGConstruct( areas, 1, wq[0] );
construct->set_cover( cover ); //construct->set_cover( cover );
construct->set_paths( work_dir, share_dir, output_dir, load_dirs ); construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
construct->set_options( ignoreLandmass, nudge ); construct->set_options( ignoreLandmass, nudge );
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
@ -207,10 +215,15 @@ int main(int argc, char **argv) {
for (unsigned int i=0; i<constructs.size(); i++) { for (unsigned int i=0; i<constructs.size(); i++) {
constructs[i]->start(); constructs[i]->start();
} }
// wait for workqueue to empty
while( wq[0].size() ) {
sleep( 5 );
}
// wait for all threads to complete // wait for all threads to complete
for (unsigned int i=0; i<constructs.size(); i++) { for (unsigned int i=0; i<constructs.size(); i++) {
constructs[i]->join(); constructs[i]->join();
} }
// delete the stage 1 construct objects // delete the stage 1 construct objects
for (unsigned int i=0; i<constructs.size(); i++) { for (unsigned int i=0; i<constructs.size(); i++) {
delete constructs[i]; delete constructs[i];
@ -218,8 +231,8 @@ int main(int argc, char **argv) {
constructs.clear(); constructs.clear();
for (int i=0; i<num_threads; i++) { for (int i=0; i<num_threads; i++) {
TGConstruct* construct = new TGConstruct( 2, wq[1] ); TGConstruct* construct = new TGConstruct( areas, 2, wq[1] );
construct->set_cover( cover ); //construct->set_cover( cover );
construct->set_paths( work_dir, share_dir, output_dir, load_dirs ); construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
construct->set_options( ignoreLandmass, nudge ); construct->set_options( ignoreLandmass, nudge );
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
@ -230,6 +243,10 @@ int main(int argc, char **argv) {
for (unsigned int i=0; i<constructs.size(); i++) { for (unsigned int i=0; i<constructs.size(); i++) {
constructs[i]->start(); constructs[i]->start();
} }
// wait for workqueue to empty
while( wq[1].size() ) {
sleep( 5 );
}
// wait for all threads to complete // wait for all threads to complete
for (unsigned int i=0; i<constructs.size(); i++) { for (unsigned int i=0; i<constructs.size(); i++) {
constructs[i]->join(); constructs[i]->join();
@ -241,8 +258,8 @@ int main(int argc, char **argv) {
constructs.clear(); constructs.clear();
for (int i=0; i<num_threads; i++) { for (int i=0; i<num_threads; i++) {
TGConstruct* construct = new TGConstruct( 3, wq[2] ); TGConstruct* construct = new TGConstruct( areas, 3, wq[2] );
construct->set_cover( cover ); //construct->set_cover( cover );
construct->set_paths( work_dir, share_dir, output_dir, load_dirs ); construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
construct->set_options( ignoreLandmass, nudge ); construct->set_options( ignoreLandmass, nudge );
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
@ -253,6 +270,10 @@ int main(int argc, char **argv) {
for (unsigned int i=0; i<constructs.size(); i++) { for (unsigned int i=0; i<constructs.size(); i++) {
constructs[i]->start(); constructs[i]->start();
} }
// wait for workqueue to empty
while( wq[2].size() ) {
sleep( 5 );
}
// wait for all threads to complete // wait for all threads to complete
for (unsigned int i=0; i<constructs.size(); i++) { for (unsigned int i=0; i<constructs.size(); i++) {
constructs[i]->join(); constructs[i]->join();

View file

@ -31,37 +31,10 @@
#include "priorities.hxx" #include "priorities.hxx"
using std::ifstream; int TGAreaDefinitions::init( const std::string& filename )
using std::string; {
using std::map; std::ifstream in ( filename.c_str() );
using std::vector; unsigned int cur_priority = 0;
typedef enum {
Hole,
Landmass,
Island,
Ocean,
Lake,
Stream,
Road,
Other
} AreaKind;
typedef struct {
string name;
AreaKind kind;
} area_type_descriptor;
typedef vector<area_type_descriptor> area_type_list;
typedef map<string, AreaType> area_name_map;
static area_type_list area_types;
static area_name_map area_names;
static AreaType default_area_type;
static AreaType sliver_target_area_type;
int load_area_types( const std::string& filename ) {
ifstream in ( filename.c_str() );
if ( ! in ) { if ( ! in ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to open priorities file " << filename); SG_LOG(SG_GENERAL, SG_ALERT, "Unable to open priorities file " << filename);
@ -70,119 +43,28 @@ int load_area_types( const std::string& filename ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Priorities file is " << filename); SG_LOG(SG_GENERAL, SG_ALERT, "Priorities file is " << filename);
in >> skipcomment; in >> skipcomment;
string sliver_area_name, default_area_name; std::string sa_name, da_name;
in >> default_area_name; in >> da_name;
in >> skipcomment; in >> skipcomment;
in >> sliver_area_name; in >> sa_name;
in >> skipcomment; in >> skipcomment;
std::string name, category;
while ( !in.eof() ) { while ( !in.eof() ) {
area_type_descriptor descriptor; in >> name;
string type; in >> category;
descriptor.kind = Other;
in >> descriptor.name;
in >> type;
if ( type=="hole" ) {
descriptor.kind = Hole;
} else if ( type=="landmass" ) {
descriptor.kind = Landmass;
} else if ( type=="island" ) {
descriptor.kind = Island;
} else if ( type=="ocean" ) {
descriptor.kind = Ocean;
} else if ( type=="lake" ) {
descriptor.kind = Lake;
} else if ( type=="stream" ) {
descriptor.kind = Stream;
} else if ( type=="road" ) {
descriptor.kind = Road;
} else if ( type=="other" ) {
descriptor.kind = Other;
}
AreaType index = (AreaType)area_types.size();
area_types.push_back(descriptor);
area_names[descriptor.name]=index;
SG_LOG(SG_GENERAL, SG_INFO, " " << index << " " << descriptor.name << " " << descriptor.kind);
in >> skipcomment; in >> skipcomment;
if ( name == sa_name ) {
sliver_area_name = sa_name;
sliver_area_priority = cur_priority;
} }
area_defs.push_back( TGAreaDefinition( name, category, cur_priority++ ) );
}
in.close(); in.close();
sliver_target_area_type = get_area_type( sliver_area_name ); return 0;
default_area_type = get_area_type( default_area_name );
return 1;
}
// return area type from text name
AreaType
get_area_type (const string &area) {
area_name_map::const_iterator it = area_names.find(area);
if (it != area_names.end()) {
return it->second;
} else {
SG_LOG(SG_GENERAL, SG_ALERT, "unknown area = '" << area << "'");
exit(-1);
}
}
static area_type_descriptor& get_area_descriptor( AreaType area ) {
if ( 0<=area || area < area_types.size() ) {
return area_types[area];
} else {
SG_LOG(SG_GENERAL, SG_ALERT, "unknown area code = " << (int)area);
exit(-1);
}
}
// return text from of area name
string get_area_name( AreaType area ) {
return get_area_descriptor( area ).name;
}
bool is_hole_area( AreaType area ) {
return get_area_descriptor( area ).kind==Hole;
}
bool is_water_area( AreaType area ) {
const AreaKind kind = get_area_descriptor( area ).kind;
return (kind==Ocean || kind==Lake || kind==Stream);
}
bool is_landmass_area( AreaType area ) {
const AreaKind kind = get_area_descriptor( area ).kind;
return (kind==Landmass);
}
bool is_island_area( AreaType area ) {
const AreaKind kind = get_area_descriptor( area ).kind;
return (kind==Island);
}
bool is_lake_area( AreaType area ) {
const AreaKind kind = get_area_descriptor( area ).kind;
return (kind==Lake);
}
bool is_stream_area( AreaType area ) {
const AreaKind kind = get_area_descriptor( area ).kind;
return (kind==Stream);
}
bool is_road_area( AreaType area ) {
const AreaKind kind = get_area_descriptor( area ).kind;
return (kind==Road);
}
bool is_ocean_area( AreaType area ) {
const AreaKind kind = get_area_descriptor( area ).kind;
return (kind==Ocean);
}
AreaType get_sliver_target_area_type() {
return sliver_target_area_type;
}
AreaType get_default_area_type() {
return default_area_type;
} }

View file

@ -24,29 +24,151 @@
#ifndef _PRIORITIES_HXX #ifndef _PRIORITIES_HXX
#define _PRIORITIES_HXX #define _PRIORITIES_HXX
#include <map>
#include <string>
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <string> #include <terragear/tg_polygon.hxx>
typedef unsigned int AreaType; class TGAreaDefinition {
int load_area_types( const std::string& filename ); public:
bool is_hole_area(AreaType areaType); TGAreaDefinition( const std::string& n, const std::string& c, unsigned int p ) {
bool is_landmass_area(AreaType areaType); name = n;
bool is_island_area(AreaType areaType); category = c;
bool is_water_area(AreaType areaType); priority = p;
bool is_lake_area(AreaType areaType); };
bool is_stream_area(AreaType areaType);
bool is_road_area(AreaType areaType);
bool is_ocean_area(AreaType areaType);
AreaType get_sliver_target_area_type();
AreaType get_default_area_type();
// return area type from text name std::string const& GetName() const {
AreaType get_area_type( const std::string &area ); return name;
}
// return text form of area name unsigned int GetPriority() const {
std::string get_area_name( AreaType area ); return priority;
}
std::string const& GetCategory() const {
return category;
}
private:
std::string name;
unsigned int priority;
std::string category;
// future improvements
unsigned int smooth_method;
tgTexMethod texture_method;
bool layered;
unsigned int default_layer;
};
typedef std::vector<TGAreaDefinition> area_definition_list;
typedef area_definition_list::const_iterator area_definition_iterator;
class TGAreaDefinitions {
public:
TGAreaDefinitions() {};
int init( const std::string& filename );
unsigned int size() const {
return area_defs.size();
}
bool is_hole_area( unsigned int p ) const {
if ( area_defs[p].GetCategory() == "hole" ) {
return true;
} else {
return false;
}
}
bool is_landmass_area( unsigned int p ) const {
if ( area_defs[p].GetCategory() == "landmass" ) {
return true;
} else {
return false;
}
}
bool is_island_area( unsigned int p ) const {
if ( area_defs[p].GetCategory() == "island" ) {
return true;
} else {
return false;
}
}
bool is_road_area( unsigned int p ) const {
if ( area_defs[p].GetCategory() == "road" ) {
return true;
} else {
return false;
}
}
bool is_water_area( unsigned int p ) const {
if ( ( area_defs[p].GetCategory() == "ocean" ) ||
( area_defs[p].GetCategory() == "lake" ) ){
return true;
} else {
return false;
}
}
bool is_lake_area( unsigned int p ) const {
if ( area_defs[p].GetCategory() == "lake" ) {
return true;
} else {
return false;
}
}
bool is_stream_area( unsigned int p ) const {
if ( area_defs[p].GetCategory() == "stream" ) {
return true;
} else {
return false;
}
}
bool is_ocean_area( unsigned int p ) const {
if ( area_defs[p].GetCategory() == "ocean" ) {
return true;
} else {
return false;
}
}
std::string const& get_area_name( unsigned int p ) const {
return area_defs[p].GetName();
}
unsigned int get_area_priority( const std::string& name ) const {
for (unsigned int i=0; i < area_defs.size(); i++) {
if ( area_defs[i].GetName() == name ) {
return i;
}
}
SG_LOG(SG_GENERAL, SG_ALERT, "No area named " << name);
exit(0);
return 0;
}
std::string const& get_sliver_area_name( void ) const {
return sliver_area_name;
}
unsigned int get_sliver_area_priority( void ) const {
return sliver_area_priority;
}
private:
area_definition_list area_defs;
std::string sliver_area_name;
unsigned int sliver_area_priority;
};
#endif // _PRIORITIES_HXX #endif // _PRIORITIES_HXX

View file

@ -33,7 +33,8 @@
const double TGConstruct::gSnap = 0.00000001; // approx 1 mm const double TGConstruct::gSnap = 0.00000001; // approx 1 mm
// Constructor // Constructor
TGConstruct::TGConstruct(unsigned int s, SGLockedQueue<SGBucket>& q) : TGConstruct::TGConstruct( const TGAreaDefinitions& areas, unsigned int s, SGLockedQueue<SGBucket>& q) :
area_defs(areas),
workQueue(q), workQueue(q),
stage(s), stage(s),
ignoreLandmass(false), ignoreLandmass(false),
@ -42,13 +43,12 @@ TGConstruct::TGConstruct(unsigned int s, SGLockedQueue<SGBucket>& q) :
isOcean(false) isOcean(false)
{ {
total_tiles = q.size(); total_tiles = q.size();
num_areas = areas.size();
} }
// Destructor // Destructor
TGConstruct::~TGConstruct() { TGConstruct::~TGConstruct() {
array.close();
// land class polygons // land class polygons
polys_in.clear(); polys_in.clear();
polys_clipped.clear(); polys_clipped.clear();
@ -82,8 +82,14 @@ void TGConstruct::run()
// assume non ocean tile until proven otherwise // assume non ocean tile until proven otherwise
isOcean = false; isOcean = false;
SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Construct in " << bucket.gen_base_path() << " tile " << tiles_complete << " of " << total_tiles ); // Initialize the landclass lists with the number of area definitions
polys_in.init( num_areas );
polys_clipped.init( num_areas );
SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Construct in " << bucket.gen_base_path() << " tile " << tiles_complete << " of " << total_tiles << " using thread " << current() );
// Init debug shapes and area for this bucket
get_debug();
if ( debug_shapes.size() || debug_all ) { if ( debug_shapes.size() || debug_all ) {
sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() );
} else { } else {
@ -92,6 +98,7 @@ void TGConstruct::run()
if ( stage > 1 ) { if ( stage > 1 ) {
LoadFromIntermediateFiles( stage-1 ); LoadFromIntermediateFiles( stage-1 );
LoadSharedEdgeData( stage-1 );
} }
switch( stage ) { switch( stage ) {
@ -110,12 +117,14 @@ void TGConstruct::run()
break; break;
} }
#if 0
// STEP 3) // STEP 3)
// Load the land use polygons if the --cover option was specified // Load the land use polygons if the --cover option was specified
if ( get_cover().size() > 0 ) { if ( get_cover().size() > 0 ) {
SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Loading landclass raster" ); SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Loading landclass raster" );
load_landcover(); load_landcover();
} }
#endif
// STEP 4) // STEP 4)
// Clip the Landclass polygons // Clip the Landclass polygons
@ -163,8 +172,8 @@ void TGConstruct::run()
// ONLY do this when saving edge nodes... // ONLY do this when saving edge nodes...
// STEP 11) // STEP 11)
// Generate face-connected list - needed for saving the edge data // Generate face-connected list - needed for saving the edge data
// SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Lookup Faces Per Node"); SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Lookup Faces Per Node");
// LookupFacesPerNode(); LookupFacesPerNode();
} }
break; break;
@ -230,10 +239,12 @@ void TGConstruct::run()
} }
// Clean up for next work queue item // Clean up for next work queue item
array.close(); array.unload();
polys_in.clear(); polys_in.clear();
polys_clipped.clear(); polys_clipped.clear();
nodes.clear(); nodes.clear();
neighbor_faces.clear(); neighbor_faces.clear();
debug_shapes.clear();
debug_areas.clear();
} }
} }

View file

@ -33,8 +33,6 @@
#include <simgear/threads/SGThread.hxx> #include <simgear/threads/SGThread.hxx>
#include <simgear/threads/SGQueue.hxx> #include <simgear/threads/SGQueue.hxx>
#define TG_MAX_AREA_TYPES 128
#include <Array/array.hxx> #include <Array/array.hxx>
#include <terragear//tg_nodes.hxx> #include <terragear//tg_nodes.hxx>
#include <landcover/landcover.hxx> #include <landcover/landcover.hxx>
@ -62,7 +60,7 @@ class TGConstruct : public SGThread
{ {
public: public:
// Constructor // Constructor
TGConstruct(unsigned int s, SGLockedQueue<SGBucket>& q); TGConstruct( const TGAreaDefinitions& areas, unsigned int s, SGLockedQueue<SGBucket>& q );
// Destructor // Destructor
~TGConstruct(); ~TGConstruct();
@ -71,6 +69,7 @@ public:
void SaveToIntermediateFiles( int stage ); void SaveToIntermediateFiles( int stage );
void LoadFromIntermediateFiles( int stage ); void LoadFromIntermediateFiles( int stage );
#if 0
int load_landcover (); int load_landcover ();
double measure_roughness( tgContour &contour ); double measure_roughness( tgContour &contour );
AreaType get_landcover_type (const LandCover &cover, double xpos, double ypos, double dx, double dy); AreaType get_landcover_type (const LandCover &cover, double xpos, double ypos, double dx, double dy);
@ -81,6 +80,7 @@ public:
// land cover file // land cover file
inline std::string get_cover () const { return cover; } inline std::string get_cover () const { return cover; }
inline void set_cover (const std::string &s) { cover = s; } inline void set_cover (const std::string &s) { cover = s; }
#endif
// paths // paths
void set_paths( const std::string work, const std::string share, const std::string output, const std::vector<std::string> load_dirs ); void set_paths( const std::string work, const std::string share, const std::string output, const std::vector<std::string> load_dirs );
@ -153,10 +153,13 @@ private:
void calc_normals( std::vector<SGGeod>& geod_nodes, std::vector<SGVec3d>& wgs84_nodes, tgPolygon& sp ); void calc_normals( std::vector<SGGeod>& geod_nodes, std::vector<SGVec3d>& wgs84_nodes, tgPolygon& sp );
// debug // debug
void get_debug( void );
bool IsDebugShape( unsigned int id ); bool IsDebugShape( unsigned int id );
bool IsDebugArea( unsigned int area ); bool IsDebugArea( unsigned int area );
private: private:
TGAreaDefinitions const& area_defs;
// construct stage to perform // construct stage to perform
SGLockedQueue<SGBucket>& workQueue; SGLockedQueue<SGBucket>& workQueue;
unsigned int total_tiles; unsigned int total_tiles;
@ -185,12 +188,15 @@ private:
bool debug_all; bool debug_all;
// list of shapes to dump during debug // list of debug definitions (for a whole tgconstruct run
std::vector<std::string> debug_area_defs;
std::vector<std::string> debug_shape_defs;
// list of shapes to dump during debug (for a single tile)
std::vector<unsigned int> debug_areas; std::vector<unsigned int> debug_areas;
std::vector<unsigned int> debug_shapes; std::vector<unsigned int> debug_shapes;
// OGR encode variables // OGR encode variables for debug:
// For debug:
void* ds_id; // If we are going to build shapefiles void* ds_id; // If we are going to build shapefiles
void* l_id; // datasource and layer IDs void* l_id; // datasource and layer IDs
char ds_name[128]; char ds_name[128];
@ -213,9 +219,10 @@ private:
// ocean tile? // ocean tile?
bool isOcean; bool isOcean;
unsigned int num_areas;
// Neighbor Faces // Neighbor Faces
neighbor_face_list neighbor_faces; neighbor_face_list neighbor_faces;
}; };
#endif // _CONSTRUCT_HXX #endif // _CONSTRUCT_HXX

View file

@ -38,7 +38,7 @@ void TGConstruct::FixTJunctions( void ) {
tgRectangle bb; tgRectangle bb;
// traverse each poly, and add intermediate nodes // traverse each poly, and add intermediate nodes
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) { for ( unsigned int i = 0; i < area_defs.size(); ++i ) {
for( unsigned int j = 0; j < polys_clipped.area_size(i); ++j ) { for( unsigned int j = 0; j < polys_clipped.area_size(i); ++j ) {
tgPolygon current = polys_clipped.get_poly(i, j); tgPolygon current = polys_clipped.get_poly(i, j);
bb = current.GetBoundingBox(); bb = current.GetBoundingBox();
@ -49,7 +49,7 @@ void TGConstruct::FixTJunctions( void ) {
after = current.TotalNodes(); after = current.TotalNodes();
if (before != after) { if (before != after) {
SG_LOG( SG_CLIPPER, SG_DEBUG, "Fixed T-Junctions in " << get_area_name( (AreaType)i ) << ":" << j+1 << " of " << (int)polys_clipped.area_size(i) << " nodes increased from " << before << " to " << after ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Fixed T-Junctions in " << area_defs.get_area_name(i) << ":" << j+1 << " of " << (int)polys_clipped.area_size(i) << " nodes increased from " << before << " to " << after );
} }
/* Save it back */ /* Save it back */
@ -83,7 +83,7 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_l
void TGConstruct::CleanClippedPolys() { void TGConstruct::CleanClippedPolys() {
// Clean the polys // Clean the polys
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { for ( unsigned int area = 0; area < area_defs.size(); area++ ) {
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
// step 1 : snap // step 1 : snap
tgPolygon poly = polys_clipped.get_poly(area, p); tgPolygon poly = polys_clipped.get_poly(area, p);

View file

@ -38,7 +38,6 @@ bool TGConstruct::ClipLandclassPolys( void ) {
tgPolygon remains; tgPolygon remains;
tgPolygon safety_base; tgPolygon safety_base;
tgcontour_list slivers; tgcontour_list slivers;
int i, j;
SGGeod p; SGGeod p;
SGVec2d min, max; SGVec2d min, max;
bool debug_area, debug_shape; bool debug_area, debug_shape;
@ -77,17 +76,16 @@ bool TGConstruct::ClipLandclassPolys( void ) {
tgPolygon land_mask, water_mask, island_mask; tgPolygon land_mask, water_mask, island_mask;
tgpolygon_list land_list, water_list, island_list; tgpolygon_list land_list, water_list, island_list;
for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) { for ( unsigned int i = 0; i < area_defs.size(); i++ ) {
if ( is_landmass_area( i ) && !ignoreLandmass ) { if ( area_defs.is_landmass_area(i) && !ignoreLandmass ) {
for ( unsigned int j = 0; j < polys_in.area_size(i); ++j ) { for ( unsigned int j = 0; j < polys_in.area_size(i); ++j ) {
land_list.push_back( polys_in.get_poly(i, j) ); land_list.push_back( polys_in.get_poly(i, j) );
} }
} else if ( area_defs.is_water_area(i) ) {
} else if ( is_water_area( i ) ) {
for (unsigned int j = 0; j < polys_in.area_size(i); j++) { for (unsigned int j = 0; j < polys_in.area_size(i); j++) {
water_list.push_back( polys_in.get_poly(i, j) ); water_list.push_back( polys_in.get_poly(i, j) );
} }
} else if ( is_island_area( i ) ) { } else if ( area_defs.is_island_area(i) ) {
for (unsigned int j = 0; j < polys_in.area_size(i); j++) { for (unsigned int j = 0; j < polys_in.area_size(i); j++) {
island_list.push_back( polys_in.get_poly(i, j) ); island_list.push_back( polys_in.get_poly(i, j) );
} }
@ -106,23 +104,23 @@ bool TGConstruct::ClipLandclassPolys( void ) {
} }
// process polygons in priority order // process polygons in priority order
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) { for ( unsigned int i = 0; i < area_defs.size(); i++ ) {
debug_area = IsDebugArea( i ); debug_area = IsDebugArea( i );
for( j = 0; j < (int)polys_in.area_size(i); ++j ) { for( unsigned int j = 0; j < polys_in.area_size(i); ++j ) {
tgPolygon& current = polys_in.get_poly(i, j); tgPolygon& current = polys_in.get_poly(i, j);
debug_shape = IsDebugShape( polys_in.get_poly( i, j ).GetId() ); debug_shape = IsDebugShape( polys_in.get_poly( i, j ).GetId() );
SG_LOG( SG_CLIPPER, SG_DEBUG, "Clipping " << get_area_name( (AreaType)i ) << "(" << i << "):" << j+1 << " of " << polys_in.area_size(i) << " id " << polys_in.get_poly( i, j ).GetId() ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Clipping " << area_defs.get_area_name( i ) << "(" << i << "):" << j+1 << " of " << polys_in.area_size(i) << " id " << polys_in.get_poly( i, j ).GetId() );
tmp = current; tmp = current;
// if not a hole, clip the area to the land_mask // if not a hole, clip the area to the land_mask
if ( !ignoreLandmass && !is_hole_area( i ) ) { if ( !ignoreLandmass && !area_defs.is_hole_area(i) ) {
tmp = tgPolygon::Intersect( tmp, land_mask ); tmp = tgPolygon::Intersect( tmp, land_mask );
} }
// if a water area, cut out potential islands // if a water area, cut out potential islands
if ( is_water_area( i ) ) { if ( area_defs.is_water_area(i) ) {
// clip against island mask // clip against island mask
tmp = tgPolygon::Diff( tmp, island_mask ); tmp = tgPolygon::Diff( tmp, island_mask );
} }
@ -136,7 +134,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
tgShapefile::FromPolygon( tmp, ds_name, layer, name ); tgShapefile::FromPolygon( tmp, ds_name, layer, name );
sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() ); sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() );
accum.ToShapefiles( ds_name, layer ); accum.ToShapefiles( ds_name, layer, true );
} }
clipped = accum.Diff( tmp ); clipped = accum.Diff( tmp );
@ -180,7 +178,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
char layer[32]; char layer[32];
sprintf(layer, "post_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() ); sprintf(layer, "post_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() );
accum.ToShapefiles( ds_name, layer ); accum.ToShapefiles( ds_name, layer, true );
} }
accum_idx++; accum_idx++;
@ -231,18 +229,18 @@ bool TGConstruct::ClipLandclassPolys( void ) {
#endif #endif
if ( remains.Contours() > 0 ) { if ( remains.Contours() > 0 ) {
remains.SetMaterial( get_area_name(get_sliver_target_area_type()) ); remains.SetMaterial( area_defs.get_sliver_area_name() );
remains.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() ); remains.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() );
polys_clipped.add_poly( (int)get_sliver_target_area_type(), remains ); polys_clipped.add_poly( area_defs.get_sliver_area_priority(), remains );
} }
} }
// Now make sure any newly added intersection nodes are added to the tgnodes // Now make sure any newly added intersection nodes are added to the tgnodes
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int area = 0; area < area_defs.size(); area++) {
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
tgPolygon& poly = polys_clipped.get_poly( area, p ); tgPolygon& poly = polys_clipped.get_poly( area, p );
SG_LOG( SG_CLIPPER, SG_DEBUG, "Collecting nodes for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_clipped.area_size(area) ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Collecting nodes for " << area_defs.get_area_name(area) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
for (unsigned int con=0; con < poly.Contours(); con++) { for (unsigned int con=0; con < poly.Contours(); con++) {
for (unsigned int n = 0; n < poly.ContourSize( con ); n++) { for (unsigned int n = 0; n < poly.ContourSize( con ); n++) {

View file

@ -32,13 +32,23 @@
using std::string; using std::string;
void TGConstruct::set_debug( std::string path, std::vector<string> area_defs, std::vector<string> shape_defs ) void TGConstruct::set_debug( std::string path, std::vector<string> a_defs, std::vector<string> s_defs )
{ {
debug_path = path; debug_path = path;
debug_area_defs = a_defs;
debug_shape_defs = s_defs;
}
void TGConstruct::get_debug( void )
{
// clear out any previous entries
debug_areas.clear();
debug_shapes.clear();
/* Find any ids for our tile */ /* Find any ids for our tile */
for (unsigned int i=0; i< area_defs.size(); i++) { for (unsigned int i=0; i< debug_area_defs.size(); i++) {
string dsd = area_defs[i]; string dsd = debug_area_defs[i];
size_t d_pos = dsd.find(":"); size_t d_pos = dsd.find(":");
string tile = dsd.substr(0, d_pos); string tile = dsd.substr(0, d_pos);
@ -64,8 +74,8 @@ void TGConstruct::set_debug( std::string path, std::vector<string> area_defs, st
} }
} }
for (unsigned int i=0; i< shape_defs.size(); i++) { for (unsigned int i=0; i< debug_shape_defs.size(); i++) {
string dsd = shape_defs[i]; string dsd = debug_shape_defs[i];
size_t d_pos = dsd.find(":"); size_t d_pos = dsd.find(":");
string tile = dsd.substr(0, d_pos); string tile = dsd.substr(0, d_pos);

View file

@ -48,7 +48,6 @@ void TGConstruct::LoadElevationArray( bool add_nodes ) {
array.parse( bucket ); array.parse( bucket );
array.remove_voids( ); array.remove_voids( );
if ( add_nodes ) { if ( add_nodes ) {
std::vector<SGGeod> const& corner_list = array.get_corner_list(); std::vector<SGGeod> const& corner_list = array.get_corner_list();
for (unsigned int i=0; i<corner_list.size(); i++) { for (unsigned int i=0; i<corner_list.size(); i++) {
@ -84,10 +83,10 @@ void TGConstruct::CalcElevations( void )
nodes.get_geod_nodes(raw_nodes); nodes.get_geod_nodes(raw_nodes);
// now flatten some stuff // now flatten some stuff
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int area = 0; area < area_defs.size(); area++) {
if ( is_lake_area( (AreaType)area ) ) { if ( area_defs.is_lake_area(area) ) {
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << area_defs.get_area_name(area) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
tgPolygon poly = polys_clipped.get_poly( area, p ); tgPolygon poly = polys_clipped.get_poly( area, p );
for (unsigned int tri=0; tri < poly.Triangles(); tri++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
@ -109,9 +108,9 @@ void TGConstruct::CalcElevations( void )
} }
} }
if ( is_stream_area( (AreaType)area ) ) { if ( area_defs.is_stream_area(area) ) {
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); ++p ) {
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << area_defs.get_area_name(area) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
tgPolygon poly = polys_clipped.get_poly( area, p ); tgPolygon poly = polys_clipped.get_poly( area, p );
for (unsigned int tri=0; tri < poly.Triangles(); tri++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
@ -156,9 +155,9 @@ void TGConstruct::CalcElevations( void )
} }
} }
if ( is_road_area( (AreaType)area ) ) { if ( area_defs.is_road_area(area) ) {
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << area_defs.get_area_name(area) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
tgPolygon poly = polys_clipped.get_poly( area, p ); tgPolygon poly = polys_clipped.get_poly( area, p );
for (unsigned int tri=0; tri < poly.Triangles(); tri++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
@ -203,9 +202,9 @@ void TGConstruct::CalcElevations( void )
} }
} }
if ( is_ocean_area( (AreaType)area ) ) { if ( area_defs.is_ocean_area(area) ) {
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << area_defs.get_area_name(area) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
tgPolygon poly = polys_clipped.get_poly( area, p ); tgPolygon poly = polys_clipped.get_poly( area, p );
for (unsigned int tri=0; tri < poly.Triangles(); tri++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {

View file

@ -7,7 +7,7 @@
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the // // published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, but // This program is distributed in the hope that it will be useful, but
@ -21,6 +21,8 @@
// //
// $Id: construct.cxx,v 1.4 2004-11-19 22:25:49 curt Exp $ // $Id: construct.cxx,v 1.4 2004-11-19 22:25:49 curt Exp $
#if 0
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
@ -279,3 +281,5 @@ int TGConstruct::load_landcover()
// Return the number of polygons actually read. // Return the number of polygons actually read.
return count; return count;
} }
#endif

View file

@ -35,7 +35,7 @@
void TGConstruct::LookupNodesPerVertex( void ) void TGConstruct::LookupNodesPerVertex( void )
{ {
// for each node, traverse all the triangles - and create face lists // for each node, traverse all the triangles - and create face lists
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { for ( unsigned int area = 0; area < area_defs.size(); area++ ) {
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
tgPolygon& poly = polys_clipped.get_poly( area, p ); tgPolygon& poly = polys_clipped.get_poly( area, p );
@ -57,7 +57,7 @@ void TGConstruct::LookupNodesPerVertex( void )
void TGConstruct::LookupFacesPerNode( void ) void TGConstruct::LookupFacesPerNode( void )
{ {
// Add each face that includes a node to the node's face list // Add each face that includes a node to the node's face list
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { for ( unsigned int area = 0; area < area_defs.size(); area++ ) {
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
tgPolygon const& poly = polys_clipped.get_poly(area, p ); tgPolygon const& poly = polys_clipped.get_poly(area, p );

View file

@ -97,9 +97,9 @@ void TGConstruct::CalcFaceNormals( void )
std::vector<SGGeod> geod_nodes; std::vector<SGGeod> geod_nodes;
nodes.get_geod_nodes( geod_nodes ); nodes.get_geod_nodes( geod_nodes );
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int area = 0; area < area_defs.size(); area++) {
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
SG_LOG( SG_CLIPPER, SG_DEBUG, "Calculating face normals for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_in.area_size(area) ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Calculating face normals for " << area_defs.get_area_name(area) << ":" << p+1 << " of " << polys_in.area_size(area) );
calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, p ) ); calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, p ) );
} }
} }

View file

@ -135,11 +135,11 @@ void TGConstruct::WriteBtgFile( void )
int_list pt_n, tri_n, strip_n; int_list pt_n, tri_n, strip_n;
int_list tri_tc, strip_tc; int_list tri_tc, strip_tc;
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int area = 0; area < area_defs.size(); area++) {
// only tesselate non holes // only tesselate non holes
if ( !is_hole_area( area ) ) { if ( !area_defs.is_hole_area(area) ) {
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
SG_LOG( SG_CLIPPER, SG_DEBUG, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_clipped.area_size(area) ); SG_LOG( SG_CLIPPER, SG_DEBUG, "Ouput nodes for " << area_defs.get_area_name(area) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
tgPolygon poly = polys_clipped.get_poly(area, p); tgPolygon poly = polys_clipped.get_poly(area, p);
string material = poly.GetMaterial(); string material = poly.GetMaterial();

View file

@ -82,8 +82,9 @@ int TGConstruct::LoadLandclassPolys( void ) {
for ( unsigned int i=0; i<count; i++ ) { for ( unsigned int i=0; i<count; i++ ) {
tgPolygon poly; tgPolygon poly;
poly.LoadFromGzFile( fp ); poly.LoadFromGzFile( fp );
area = get_area_type( poly.GetFlag() ); area = area_defs.get_area_priority( poly.GetFlag() );
material = get_area_name( area ); material = area_defs.get_area_name( area );
poly.SetMaterial( material ); poly.SetMaterial( material );
poly.SetId( cur_poly_id++ ); poly.SetId( cur_poly_id++ );
@ -96,10 +97,6 @@ int TGConstruct::LoadLandclassPolys( void ) {
SGGeod const& node = poly.GetNode( j, k ); SGGeod const& node = poly.GetNode( j, k );
if ( poly.GetPreserve3D() ) { if ( poly.GetPreserve3D() ) {
if ( node.getElevationM() < 2.0 ) {
SG_LOG(SG_GENERAL, SG_ALERT, "FIXED ELEVATION NODE in POLY " << poly.GetFlag() << " has elevation " << node.getElevationM() );
}
nodes.unique_add_fixed_elevation( node ); nodes.unique_add_fixed_elevation( node );
} else { } else {
nodes.unique_add( node ); nodes.unique_add( node );
@ -107,7 +104,6 @@ int TGConstruct::LoadLandclassPolys( void ) {
} }
} }
} }
gzclose( fp );
gzclose( fp ); gzclose( fp );
SG_LOG(SG_GENERAL, SG_DEBUG, " Loaded " << p.file()); SG_LOG(SG_GENERAL, SG_DEBUG, " Loaded " << p.file());

View file

@ -37,7 +37,7 @@ void TGConstruct::TesselatePolys( void )
std::vector<SGGeod> poly_extra; std::vector<SGGeod> poly_extra;
SGGeod min, max; SGGeod min, max;
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int area = 0; area < area_defs.size(); area++) {
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
tgPolygon poly = polys_clipped.get_poly(area, p ); tgPolygon poly = polys_clipped.get_poly(area, p );
@ -48,8 +48,8 @@ void TGConstruct::TesselatePolys( void )
tgRectangle rect = poly.GetBoundingBox(); tgRectangle rect = poly.GetBoundingBox();
nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra ); nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra );
SG_LOG( SG_CLIPPER, SG_DEBUG, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " << SG_LOG( SG_CLIPPER, SG_DEBUG, "Tesselating " << area_defs.get_area_name(area) << "(" << area << "): " <<
p+1 << " of " << (int)polys_clipped.area_size(area) << ": id = " << poly.GetId() ); p+1 << " of " << polys_clipped.area_size(area) << ": id = " << poly.GetId() );
if ( IsDebugShape( poly.GetId() ) ) { if ( IsDebugShape( poly.GetId() ) ) {
SG_LOG( SG_CLIPPER, SG_INFO, poly ); SG_LOG( SG_CLIPPER, SG_INFO, poly );
@ -61,7 +61,7 @@ void TGConstruct::TesselatePolys( void )
} }
} }
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int area = 0; area < area_defs.size(); area++) {
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
tgPolygon& poly = polys_clipped.get_poly(area, p ); tgPolygon& poly = polys_clipped.get_poly(area, p );

View file

@ -30,10 +30,10 @@
void TGConstruct::CalcTextureCoordinates( void ) void TGConstruct::CalcTextureCoordinates( void )
{ {
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { for ( unsigned int area = 0; area < area_defs.size(); area++ ) {
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
tgPolygon poly = polys_clipped.get_poly(area, p); tgPolygon poly = polys_clipped.get_poly(area, p);
SG_LOG( SG_CLIPPER, SG_DEBUG, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " << SG_LOG( SG_CLIPPER, SG_DEBUG, "Texturing " << area_defs.get_area_name(area) << "(" << area << "): " <<
p+1 << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() ); p+1 << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() );
poly.Texture( ); poly.Texture( );

View file

@ -35,39 +35,45 @@
void TGLandclass::clear(void) void TGLandclass::clear(void)
{ {
int i; for (unsigned int i=0; i<polys.size(); i++) {
for (i=0; i<TG_MAX_AREA_TYPES; i++) {
polys[i].clear(); polys[i].clear();
} }
// keep the number of arrays intact - it's constant throughout construct
polys.clear();
} }
void TGLandclass::LoadFromGzFile(gzFile& fp) void TGLandclass::LoadFromGzFile(gzFile& fp)
{ {
int i, j, count; int i, j, num_layers, num_polys;
// Load all landclass shapes // Load all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) { sgReadInt( fp, &num_layers );
sgReadInt( fp, &count );
for (j=0; j<count; j++) { polys.clear();
for (i=0; i<num_layers; i++) {
tgpolygon_list lc;
sgReadInt( fp, &num_polys );
lc.clear();
for (j=0; j<num_polys; j++) {
tgPolygon poly; tgPolygon poly;
poly.LoadFromGzFile( fp ); poly.LoadFromGzFile( fp );
polys[i].push_back( poly ); lc.push_back( poly );
} }
polys.push_back(lc);
} }
} }
std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc ) std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
{ {
int i, j, count; unsigned int count;
tgPolygon poly; tgPolygon poly;
// Save all landclass shapes // Save all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) { for (unsigned int i=0; i<lc.polys.size(); i++) {
count = lc.polys[i].size(); count = lc.polys[i].size();
out << count << "\n"; out << count << "\n";
for (j=0; j<count; j++) { for (unsigned int j=0; j<count; j++) {
out << lc.polys[i][j] << " "; out << lc.polys[i][j] << " ";
} }
out << "\n"; out << "\n";
@ -75,17 +81,20 @@ std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
return out; return out;
} }
void TGLandclass::SaveToGzFile(gzFile& fp) void TGLandclass::SaveToGzFile(gzFile& fp)
{ {
int i, j, count; int i, j, num_layers, num_polys;
tgPolygon shape; tgPolygon shape;
// Save all landclass shapes // Save all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) { num_layers = polys.size();
count = polys[i].size(); sgWriteInt( fp, num_layers );
sgWriteInt( fp, count ); for (i=0; i<num_layers; i++) {
num_polys = polys[i].size();
sgWriteInt( fp, num_polys );
for (j=0; j<count; j++) { for (j=0; j<num_polys; j++) {
polys[i][j].SaveToGzFile( fp ); polys[i][j].SaveToGzFile( fp );
} }
} }

View file

@ -35,14 +35,25 @@
#include <simgear/math/sg_types.hxx> #include <simgear/math/sg_types.hxx>
#include <simgear/io/lowlevel.hxx> #include <simgear/io/lowlevel.hxx>
#include <simgear/debug/logstream.hxx>
#include <terragear/tg_polygon.hxx> #include <terragear/tg_polygon.hxx>
#define TG_MAX_AREA_TYPES 128 typedef std::vector<tgpolygon_list> tglandclass_list;
class TGLandclass class TGLandclass
{ {
public: public:
TGLandclass() {};
void init( unsigned int num_areas) {
for (unsigned int i=0; i<num_areas; i++) {
tgpolygon_list lc;
lc.clear();
polys.push_back(lc);
}
}
void clear(void); void clear(void);
inline unsigned int area_size( unsigned int area ) const inline unsigned int area_size( unsigned int area ) const
@ -60,6 +71,10 @@ public:
} }
inline void add_poly( unsigned int area, const tgPolygon& p ) inline void add_poly( unsigned int area, const tgPolygon& p )
{ {
if ( area > polys.capacity() ) {
SG_LOG( SG_CLIPPER, SG_ALERT, " area out of bounds " << area << " of " << polys.capacity() );
exit(0);
}
polys[area].push_back( p ); polys[area].push_back( p );
} }
inline void set_poly( unsigned int area, unsigned int poly, const tgPolygon& p ) inline void set_poly( unsigned int area, unsigned int poly, const tgPolygon& p )
@ -98,7 +113,7 @@ public:
friend std::ostream& operator<< ( std::ostream&, const TGLandclass& ); friend std::ostream& operator<< ( std::ostream&, const TGLandclass& );
private: private:
tgpolygon_list polys[TG_MAX_AREA_TYPES]; tglandclass_list polys;
}; };
#endif // _TGLANDCLASS_HXX #endif // _TGLANDCLASS_HXX

View file

@ -32,8 +32,9 @@ using std::ifstream;
using std::string; using std::string;
using std::vector; using std::vector;
static vector<AreaType> usgs_map; static vector<unsigned int> usgs_map;
#if 0 // need area_defs
int load_usgs_map( const std::string& filename ) { int load_usgs_map( const std::string& filename ) {
ifstream in ( filename.c_str() ); ifstream in ( filename.c_str() );
@ -57,7 +58,7 @@ int load_usgs_map( const std::string& filename ) {
} }
// Translate USGS land cover values into TerraGear area types. // Translate USGS land cover values into TerraGear area types.
AreaType translateUSGSCover (unsigned int usgs_value) unsigned int translateUSGSCover (unsigned int usgs_value)
{ {
if ( 0<usgs_value && usgs_value<usgs_map.size() ) { if ( 0<usgs_value && usgs_value<usgs_map.size() ) {
return usgs_map[usgs_value-1]; return usgs_map[usgs_value-1];
@ -65,4 +66,4 @@ AreaType translateUSGSCover (unsigned int usgs_value)
return get_default_area_type(); return get_default_area_type();
} }
} }
#endif

View file

@ -29,6 +29,6 @@
#include "priorities.hxx" #include "priorities.hxx"
int load_usgs_map( const std::string& filename ); int load_usgs_map( const std::string& filename );
AreaType translateUSGSCover( unsigned int usgs_value ); unsigned int translateUSGSCover( unsigned int usgs_value );
#endif // _USGS_HXX #endif // _USGS_HXX

View file

@ -68,7 +68,7 @@ bool TGArray::open( const string& file_base ) {
// open fitted data file // open fitted data file
string fitted_name = file_base + ".fit.gz"; string fitted_name = file_base + ".fit.gz";
fitted_in = new sg_gzifstream( fitted_name ); fitted_in = new sg_gzifstream( fitted_name );
if ( ! fitted_in->is_open() ) { if ( !fitted_in->is_open() ) {
// not having a .fit file is unfortunate, but not fatal. We // not having a .fit file is unfortunate, but not fatal. We
// can do a really stupid/crude fit on the fly, but it will // can do a really stupid/crude fit on the fly, but it will
// not be nearly as nice as what the offline terrafit utility // not be nearly as nice as what the offline terrafit utility
@ -101,6 +101,27 @@ TGArray::close() {
return true; return true;
} }
void
TGArray::unload( void ) {
if (array_in) {
gzclose(array_in);
array_in = NULL;
}
if (fitted_in ) {
fitted_in->close();
delete fitted_in;
fitted_in = NULL;
}
if (in_data) {
delete[] in_data;
in_data = NULL;
}
corner_list.clear();
fitted_list.clear();
}
// parse Array file, pass in the bucket so we can make up values when // parse Array file, pass in the bucket so we can make up values when
// the file wasn't found. // the file wasn't found.
@ -430,7 +451,21 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
TGArray::~TGArray( void ) TGArray::~TGArray( void )
{ {
if (in_data) {
delete[] in_data; delete[] in_data;
in_data = NULL;
}
if (array_in) {
gzclose(array_in);
array_in = NULL;
}
if (fitted_in ) {
fitted_in->close();
delete fitted_in;
fitted_in = NULL;
}
} }
int TGArray::get_array_elev( int col, int row ) const int TGArray::get_array_elev( int col, int row ) const

View file

@ -102,6 +102,9 @@ public:
int get_array_elev( int col, int row ) const; int get_array_elev( int col, int row ) const;
void set_array_elev( int col, int row, int val ); void set_array_elev( int col, int row, int val );
// reset Array to initial state - ready to load another elevation file
void unload( void );
}; };
#endif // _ARRAY_HXX #endif // _ARRAY_HXX

View file

@ -59,16 +59,29 @@ void tgAccumulator::Add( const tgContour& subject )
accum.push_back( clipper_subject ); accum.push_back( clipper_subject );
} }
void tgAccumulator::ToShapefiles( const std::string& path, const std::string& layer_prefix ) void tgAccumulator::ToShapefiles( const std::string& path, const std::string& layer_prefix, bool individual )
{ {
char shapefile[16]; char shapefile[16];
char layer[16]; char layer[16];
if ( individual ) {
for (unsigned int i=0; i < accum.size(); i++) { for (unsigned int i=0; i < accum.size(); i++) {
sprintf( layer, "%s_%d", layer_prefix.c_str(), i ); sprintf( layer, "%s_%d", layer_prefix.c_str(), i );
sprintf( shapefile, "accum_%d", i ); sprintf( shapefile, "accum_%d", i );
tgShapefile::FromClipper( accum[i], path, layer, std::string(shapefile) ); tgShapefile::FromClipper( accum[i], path, layer, std::string(shapefile) );
} }
} else {
ClipperLib::Polygons clipper_result;
ClipperLib::Clipper c;
c.Clear();
for ( unsigned int i=0; i<accum.size(); i++ ) {
c.AddPolygons(accum[i], ClipperLib::ptSubject);
}
c.Execute( ClipperLib::ctUnion, clipper_result, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
tgShapefile::FromClipper( clipper_result, path, layer_prefix, "accum" );
}
} }
tgPolygon tgAccumulator::Diff( const tgPolygon& subject ) tgPolygon tgAccumulator::Diff( const tgPolygon& subject )

View file

@ -14,7 +14,7 @@ public:
void Add( const tgContour& subject ); void Add( const tgContour& subject );
void Add( const tgPolygon& subject ); void Add( const tgPolygon& subject );
void ToShapefiles( const std::string& path, const std::string& layer ); void ToShapefiles( const std::string& path, const std::string& layer, bool individual );
private: private:
typedef std::vector < ClipperLib::Polygons > clipper_polygons_list; typedef std::vector < ClipperLib::Polygons > clipper_polygons_list;

View file

@ -200,11 +200,9 @@ long int tgChopper::GenerateIndex( std::string path )
long int index = 0; long int index = 0;
//Open or create the named mutex //Open or create the named mutex
boost::interprocess::named_mutex mutex(boost::interprocess::open_or_create, "tgChopper_index2"); boost::interprocess::named_mutex mutex(boost::interprocess::open_or_create, "tgChopper_index3");
{ {
// SG_LOG(SG_GENERAL, SG_ALERT, "getting lock");
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(mutex); boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(mutex);
// SG_LOG(SG_GENERAL, SG_ALERT, " - got it");
/* first try to read the file */ /* first try to read the file */
FILE *fp = fopen( index_file.c_str(), "r+" ); FILE *fp = fopen( index_file.c_str(), "r+" );
@ -218,7 +216,6 @@ long int tgChopper::GenerateIndex( std::string path )
} }
} else { } else {
fread( (void*)&index, sizeof(long int), 1, fp ); fread( (void*)&index, sizeof(long int), 1, fp );
// SG_LOG(SG_GENERAL, SG_ALERT, " SUCCESS READING INDEX FILE - READ INDEX " << index );
} }
index++; index++;

View file

@ -54,11 +54,15 @@ public:
kd_tree_valid = false; kd_tree_valid = false;
} }
~TGNodes( void ) {} ~TGNodes( void ) {
tg_node_list.clear();
tg_kd_tree.clear();
}
// delete all the data out of node_list // delete all the data out of node_list
inline void clear() { inline void clear() {
tg_node_list.clear(); tg_node_list.clear();
tg_kd_tree.clear();
kd_tree_valid = false; kd_tree_valid = false;
} }

View file

@ -346,13 +346,13 @@ void tgPolygon::LoadFromGzFile( gzFile& fp )
sgReadString( fp, &strbuff ); sgReadString( fp, &strbuff );
if ( strbuff ) { if ( strbuff ) {
material = strbuff; material = strbuff;
delete strbuff; delete[] strbuff;
} }
sgReadString( fp, &strbuff ); sgReadString( fp, &strbuff );
if ( strbuff ) { if ( strbuff ) {
flag = strbuff; flag = strbuff;
delete strbuff; delete[] strbuff;
} }
sgReadInt( fp, (int *)&preserve3d ); sgReadInt( fp, (int *)&preserve3d );

View file

@ -212,6 +212,10 @@ public:
tgPolygon() { tgPolygon() {
preserve3d = false; preserve3d = false;
} }
~tgPolygon() {
contours.clear();
triangles.clear();
}
void Erase( void ) { void Erase( void ) {
contours.clear(); contours.clear();

View file

@ -121,6 +121,11 @@ void tgShapefile::FromClipper( const ClipperLib::Polygons& subject, const std::s
OGRFeature::DestroyFeature(feature); OGRFeature::DestroyFeature(feature);
} }
// close after each write
if ( ds_id >= 0 ) {
ds_id = tgShapefile::CloseDatasource( ds_id );
}
} }
void tgShapefile::FromPolygon( const tgPolygon& subject, const std::string& datasource, const std::string& layer, const std::string& description ) void tgShapefile::FromPolygon( const tgPolygon& subject, const std::string& datasource, const std::string& layer, const std::string& description )

View file

@ -192,6 +192,11 @@ class UniqueTGNodeSet {
public: public:
UniqueTGNodeSet() {} UniqueTGNodeSet() {}
~UniqueTGNodeSet() {
index_list.clear();
node_list.clear();
}
unsigned int add( const TGNode& n ) { unsigned int add( const TGNode& n ) {
unique_tgnode_set_iterator it; unique_tgnode_set_iterator it;
TGNodeIndex lookup( n.GetPosition() ); TGNodeIndex lookup( n.GetPosition() );