1
0
Fork 0

Read the priorities for materials from a data file (closes #5)

This commit is contained in:
Ralf Gerlich 2009-12-20 11:47:19 +01:00
parent 824d734eb4
commit 61ac48f3e5
10 changed files with 573 additions and 552 deletions

View file

@ -1,7 +1,7 @@
noinst_LIBRARIES = libClipper.a
libClipper_a_SOURCES = clipper.cxx clipper.hxx priorities.cxx priorities.hxx
dist_pkgdata_DATA = default_priorities.txt
noinst_PROGRAMS = testclipper
testclipper_SOURCES = testclipper.cxx
@ -19,3 +19,4 @@ testclipper_LDADD = \
-lgenpolyclip -lz
INCLUDES = -I$(top_srcdir)/src/Lib -I$(top_srcdir)/src/BuildTiles

View file

@ -73,7 +73,7 @@ bool TGClipper::load_polys(const string& path) {
bool poly3d = false;
string first_line;
string poly_name;
AreaType poly_type = DefaultArea;
AreaType poly_type;
int contours, count, i, j;
int hole_flag;
double startx, starty, startz, x, y, z, lastx, lasty, lastz;
@ -172,17 +172,17 @@ bool TGClipper::load_polys(const string& path) {
}
}
}
int area = (int)poly_type;
add_poly(area, poly);
// FILE *ofp= fopen("outfile", "w");
// gpc_write_polygon(ofp, &polys.landuse);
in >> skipcomment;
}
int area = (int)poly_type;
add_poly(area, poly);
// FILE *ofp= fopen("outfile", "w");
// gpc_write_polygon(ofp, &polys.landuse);
return true;
}
@ -192,7 +192,7 @@ bool TGClipper::load_polys(const string& path) {
bool TGClipper::load_osgb36_polys(const string& path) {
// cout << "Loading osgb36 poly\n";
string poly_name;
AreaType poly_type = DefaultArea;
AreaType poly_type;
int contours, count, i, j;
int hole_flag;
double startx, starty, x, y, lastx, lasty;
@ -275,26 +275,16 @@ bool TGClipper::load_osgb36_polys(const string& path) {
// gpc_add_contour( poly, &v_list, hole_flag );
}
int area = (int)poly_type;
add_poly( area, poly);
// FILE *ofp= fopen("outfile", "w");
// gpc_write_polygon(ofp, &polys.landuse);
in >> skipcomment;
}
int area = (int)poly_type;
// if ( area == OceanArea ) {
// TEST - Ignore
// } else
if ( area < TG_MAX_AREA_TYPES ) {
polys_in.polys[area].push_back(poly);
} else {
SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon type out of range = "
<< (int)poly_type);
exit(-1);
}
// FILE *ofp= fopen("outfile", "w");
// gpc_write_polygon(ofp, &polys.landuse);
return true;
}
@ -391,7 +381,7 @@ void TGClipper::merge_slivers( TGPolyList& clipped, TGPolygon& slivers ) {
for ( area = 0; area < TG_MAX_AREA_TYPES && !done; ++area ) {
if ( area == HoleArea ) {
if ( is_hole_area( area ) ) {
// don't merge a non-hole sliver in with a hole
continue;
}
@ -438,31 +428,6 @@ void TGClipper::merge_slivers( TGPolyList& clipped, TGPolygon& slivers ) {
}
static bool
is_water_area (AreaType type)
{
switch (type) {
case PondArea:
case LakeArea:
case DryLakeArea:
case IntLakeArea:
case ReservoirArea:
case IntReservoirArea:
case StreamArea:
case IntStreamArea:
case CanalArea:
case OceanArea:
case BogArea:
case MarshArea:
case LittoralArea:
case WaterBodyCover:
return true;
default:
return false;
}
}
// Clip all the polygons against each other in a priority scheme based
// on order of the polygon type in the polygon type enum.
bool TGClipper::clip_all(const point2d& min, const point2d& max) {
@ -490,33 +455,30 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
// 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.
TGPolygon land_mask;
// also set up a mask for all water and islands
TGPolygon land_mask, water_mask, island_mask;
land_mask.erase();
for ( i = 0; i < (int)polys_in.polys[DefaultArea].size(); ++i ) {
land_mask =
tgPolygonUnion( land_mask, polys_in.polys[DefaultArea][i] );
}
// set up a mask for all water.
TGPolygon water_mask;
water_mask.erase();
island_mask.erase();
for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) {
if (is_water_area(AreaType(i))) {
if ( is_landmass_area( i ) ) {
for ( unsigned j = 0; j < (int)polys_in.polys[i].size(); ++j ) {
land_mask =
tgPolygonUnion( land_mask, polys_in.polys[i][j] );
}
} else if ( is_water_area( i ) ) {
for (unsigned int j = 0; j < polys_in.polys[i].size(); j++) {
water_mask =
tgPolygonUnion( water_mask, polys_in.polys[i][j] );
}
} else if ( is_water_area( i ) ) {
for (unsigned int j = 0; j < polys_in.polys[i].size(); j++) {
island_mask =
tgPolygonUnion( island_mask, polys_in.polys[i][j] );
}
}
}
// set up island mask, for cutting holes in lakes
TGPolygon island_mask;
island_mask.erase();
for ( i = 0; i < (int)polys_in.polys[IslandArea].size(); ++i ) {
island_mask =
tgPolygonUnion( island_mask, polys_in.polys[IslandArea][i] );
}
// process polygons in priority order
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
cout << "num polys of type (" << i << ") = "
@ -529,7 +491,7 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
tmp = current;
// if not a hole, clip the area to the land_mask
if ( i != HoleArea ) {
if ( ! is_hole_area( i ) ) {
tmp = tgPolygonInt( tmp, land_mask );
}
@ -549,7 +511,7 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
// }
// if a water area, cut out potential islands
if ( is_water_area(AreaType(i)) ) {
if ( is_water_area( i ) ) {
// clip against island mask
tmp = tgPolygonDiff( tmp, island_mask );
}
@ -615,7 +577,7 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
}
if ( remains.contours() > 0 ) {
polys_clipped.polys[(int)OceanArea].push_back(remains);
polys_clipped.polys[(int)get_sliver_target_area_type()].push_back(remains);
}
}

View file

@ -0,0 +1,68 @@
Default # Default area which can be overridden by
# raster landcover data (e.g. USGS)
Ocean # collect slivers as ocean
# Area types in order of descending priority
SomeSort other
Hole hole # Leave area completely empty
Airport other
Freeway road
Road road
Railroad road
Pond lake
Lake lake
DryLake lake
IntLake lake
Reservoir lake
IntReservoir lake
Stream stream
IntStream stream
Canal stream
Glacier other # Solid ice/snow
PackIce other # Water with ice packs
PolarIce other
Ocean ocean
Urban other # Densely-populated city or large town
Town other # Small town or village
FloodLand other # Land subject to flooding
Bog other # Bog
Marsh other # Marshland or swamp
Sand other # Sand-covered area
Littoral other # Tidal, Sand-covered area
Lava other # Lava-covered area
# USGS Land Covers
# These are low-priority, since known polygons should always win.
BuiltUpCover other # Urban and Built-Up Land
DryCropPastureCover other # Dryland Cropland and Pasture
IrrCropPastureCover other # Irrigated Cropland and Pasture
MixedCropPastureCover other # Mixed Dryland/Irrigated Cropland and Pasture
CropGrassCover other # Cropland/Grassland Mosaic
CropWoodCover other # Cropland/Woodland Mosaic
GrassCover other # Grassland
ShrubCover other # Shrubland
ShrubGrassCover other # Mixed Shrubland/Grassland
SavannaCover other # Savanna
DeciduousBroadCover other # Deciduous Broadleaf Forest
DeciduousNeedleCover other # Deciduous Needleleaf Forest
EvergreenBroadCover other # Evergreen Broadleaf Forest
EvergreenNeedleCover other # Evergreen Needleleaf Forest
MixedForestCover other # Mixed Forest
WaterBodyCover lake # Water Bodies
HerbWetlandCover other # Herbaceous Wetland
WoodedWetlandCover other # Wooded Wetland
BarrenCover other # Barren or Sparsely Vegetated
HerbTundraCover other # Herbaceous Tundra
WoodedTundraCover other # Wooded Tundra
MixedTundraCover other # Mixed Tundra
BareTundraCover other # Bare Ground Tundra
SnowCover other # Snow or Ice
Island island # any island area not covered otherwise
Default landmass # any land area not covered otherwise
Void other
Null other
Unknown other

View file

@ -17,133 +17,165 @@
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <stdlib.h>
#include "priorities.hxx"
using std::fstream;
using std::string;
using std::map;
using std::vector;
typedef map<AreaType, string> area_type_map;
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_map area_types;
static area_type_list area_types;
static area_name_map area_names;
static AreaType default_area_type;
static AreaType sliver_target_area_type;
inline static void set_area (const string &name, AreaType type)
{
area_types[type] = name;
area_names[name] = type;
int load_area_types( const std::string& filename ) {
fstream in ( filename.c_str() );
if ( ! in ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to open file " << filename);
return 0;
}
in >> skipcomment;
string sliver_area_name, default_area_name;
in >> default_area_name;
in >> skipcomment;
in >> sliver_area_name;
in >> skipcomment;
while ( !in.eof() ) {
area_type_descriptor descriptor;
string type;
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, " " << descriptor.name << " " << descriptor.kind);
in >> skipcomment;
}
in.close();
sliver_target_area_type = get_area_type( sliver_area_name );
default_area_type = get_area_type( default_area_name );
return 1;
}
static bool _initialized = false;
inline static void init ()
{
if (_initialized)
return;
set_area("SomeSort", SomeSortOfArea);
set_area("Hole", HoleArea);
set_area("Airport", AirportArea);
set_area("Island", IslandArea);
set_area("Pond", PondArea);
set_area("Swamp or Marsh", MarshArea);
set_area("Marsh", MarshArea);
set_area("Littoral", LittoralArea);
set_area("Bog", BogArea);
set_area("Sand", SandArea);
set_area("Lava", LavaArea);
set_area("FloodLand", FloodLandArea);
set_area("Lake", LakeArea);
set_area("Lake Dry", DryLakeArea);
set_area("DryLake", DryLakeArea);
set_area("Lake Intermittent", IntLakeArea);
set_area("IntermittentLake", IntLakeArea);
set_area("Reservoir", ReservoirArea);
set_area("Reservoir Intermittent", IntReservoirArea);
set_area("IntermittentReservoir", IntReservoirArea);
set_area("Freeway", FreewayArea);
set_area("Road", RoadArea);
set_area("Railroad", RailroadArea);
set_area("Stream", StreamArea);
set_area("IntermittentStream", IntStreamArea);
set_area("Canal", CanalArea);
set_area("Glacier", GlacierArea);
set_area("PackIce", PackIceArea);
set_area("PolarIce", PolarIceArea);
set_area("Urban", UrbanArea);
set_area("Town", TownArea);
set_area("BuiltUpCover", BuiltUpCover);
set_area("DryCropPastureCover", DryCropPastureCover);
set_area("IrrCropPastureCover", IrrCropPastureCover);
set_area("MixedCropPastureCover", MixedCropPastureCover);
set_area("CropGrassCover", CropGrassCover);
set_area("CropWoodCover", CropWoodCover);
set_area("GrassCover", GrassCover);
set_area("ShrubCover", ShrubCover);
set_area("ShrubGrassCover", ShrubGrassCover);
set_area("SavannaCover", SavannaCover);
set_area("DeciduousBroadCover", DeciduousBroadCover);
set_area("DeciduousNeedleCover", DeciduousNeedleCover);
set_area("EvergreenBroadCover", EvergreenBroadCover);
set_area("EvergreenNeedleCover", EvergreenNeedleCover);
set_area("MixedForestCover", MixedForestCover);
set_area("WaterBodyCover", WaterBodyCover);
set_area("HerbWetlandCover", HerbWetlandCover);
set_area("WoodedWetlandCover", WoodedWetlandCover);
set_area("BarrenCover", BarrenCover);
set_area("HerbTundraCover", HerbTundraCover);
set_area("WoodedTundraCover", WoodedTundraCover);
set_area("MixedTundraCover", MixedTundraCover);
set_area("BareTundraCover", BareTundraCover);
set_area("SnowCover", SnowCover);
set_area("Default", DefaultArea);
set_area("Bay Estuary or Ocean", OceanArea);
set_area("Ocean", OceanArea);
set_area("Void Area", VoidArea);
set_area("Null", NullArea);
_initialized = true;
}
// return area type from text name
AreaType
get_area_type (const string &area) {
init();
area_name_map::const_iterator it = area_names.find(area);
if (it != area_names.end()) {
return it->second;
} else {
SG_LOG(SG_GENERAL, SG_WARN, "unknown area = '" << area << "'");
// SG_LOG(SG_GENERAL, SG_DEBUG, "area = " << area);
// for ( int i = 0; i < area.length(); i++ ) {
// SG_LOG(SG_GENERAL, SG_DEBUG, i << ") " << (int)area[i]);
// }
return UnknownArea;
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 ) {
init();
area_type_map::const_iterator it = area_types.find(area);
if (it != area_types.end()) {
return it->second;
} else {
SG_LOG(SG_GENERAL, SG_WARN, "unknown area code = " << (int)area);
return "Unknown";
}
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 ) {
return get_area_descriptor( area ).kind==Landmass;
}
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

@ -29,74 +29,17 @@
#include <string>
// Posible shape file types. Note the order of these is important and
// defines the priority of these shapes if they should intersect. The
// smaller the number, the higher the priority.
enum AreaType {
SomeSortOfArea = 0,
HoleArea, // Leave area completely empty
AirportArea,
FreewayArea,
RoadArea,
RailroadArea,
PondArea,
LakeArea,
DryLakeArea,
IntLakeArea,
ReservoirArea,
IntReservoirArea,
StreamArea,
IntStreamArea,
CanalArea,
GlacierArea, // Solid ice/snow
PackIceArea, // Water with ice packs
PolarIceArea,
OceanArea,
UrbanArea, // Densely-populated city or large town
TownArea, // Small town or village
FloodLandArea, // Land subject to flooding
BogArea, // Bog
MarshArea, // Marshland or swamp
SandArea, // Sand-covered area
LittoralArea, // Tidal, Sand-covered area
LavaArea, // Lava-covered area
// USGS Land Covers
// These are low-priority, since known polygons should always win.
BuiltUpCover, // Urban and Built-Up Land
DryCropPastureCover, // Dryland Cropland and Pasture
IrrCropPastureCover, // Irrigated Cropland and Pasture
MixedCropPastureCover, // Mixed Dryland/Irrigated Cropland and Pasture
CropGrassCover, // Cropland/Grassland Mosaic
CropWoodCover, // Cropland/Woodland Mosaic
GrassCover, // Grassland
ShrubCover, // Shrubland
ShrubGrassCover, // Mixed Shrubland/Grassland
SavannaCover, // Savanna
DeciduousBroadCover, // Deciduous Broadleaf Forest
DeciduousNeedleCover, // Deciduous Needleleaf Forest
EvergreenBroadCover, // Evergreen Broadleaf Forest
EvergreenNeedleCover, // Evergreen Needleleaf Forest
MixedForestCover, // Mixed Forest
WaterBodyCover, // Water Bodies
HerbWetlandCover, // Herbaceous Wetland
WoodedWetlandCover, // Wooded Wetland
BarrenCover, // Barren or Sparsely Vegetated
HerbTundraCover, // Herbaceous Tundra
WoodedTundraCover, // Wooded Tundra
MixedTundraCover, // Mixed Tundra
BareTundraCover, // Bare Ground Tundra
SnowCover, // Snow or Ice
IslandArea, // any island area not covered otherwise
DefaultArea, // any land area not covered otherwise
VoidArea,
NullArea,
UnknownArea
};
typedef unsigned int AreaType;
int load_area_types( const std::string& filename );
bool is_hole_area(AreaType areaType);
bool is_landmass_area(AreaType areaType);
bool is_water_area(AreaType areaType);
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
AreaType get_area_type( const std::string &area );

View file

@ -26,9 +26,11 @@ fgfs_construct_LDADD = \
fgfs_master_SOURCES = master.cxx
fgfs_master_LDADD = -lsgbucket -lsgmisc -lsgdebug -lsgxml
AM_CPPFLAGS = -DDEFAULT_USGS_MAPFILE="\"$(pkgdatadir)/usgsmap.txt\""
AM_CPPFLAGS = -DDEFAULT_USGS_MAPFILE="\"$(pkgdatadir)/usgsmap.txt\"" \
-DDEFAULT_PRIORITIES_FILE="\"$(pkgdatadir)/default_priorities.txt\""
INCLUDES = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/Lib \
-I$(top_srcdir)/src/BuildTiles

View file

@ -154,7 +154,7 @@ static AreaType get_area_type (const LandCover &cover,
int cover_value = cover.getValue(xpos, ypos);
AreaType area = translateUSGSCover(cover_value);
if (area != DefaultArea) {
if ( area != get_default_area_type() ) {
// Non-default area is fine.
return area;
} else {
@ -165,7 +165,7 @@ static AreaType get_area_type (const LandCover &cover,
if (x != xpos || y != ypos) {
cover_value = cover.getValue(x, y);
area = translateUSGSCover(cover_value);
if (area != DefaultArea) {
if (area != get_default_area_type() ) {
return area;
}
}
@ -174,7 +174,7 @@ static AreaType get_area_type (const LandCover &cover,
}
// OK, give up and return default
return DefaultArea;
return get_default_area_type();
}
@ -232,7 +232,7 @@ static void make_area( const LandCover &cover, const TGArray &array,
AreaType area = get_area_type( cover,
x1 + half_dx, y1 + half_dy,
x2 - x1, y2 - y1 );
if (area != DefaultArea) {
if ( area != get_default_area_type() ) {
// Create a square polygon and merge it into the list.
TGPolygon poly;
poly.erase();
@ -512,7 +512,7 @@ static void fix_point_heights( TGConstruct& c, const TGArray& array )
// It might be better to eventually iterate, and allow
// some flexibility in elevations to handle rivers and
// things like that.
if ( (a == LakeArea) || (a == ReservoirArea) ) {
if ( is_lake_area( a ) ) {
e1 = raw_nodes[n1].z();
e2 = raw_nodes[n2].z();
e3 = raw_nodes[n3].z();
@ -525,8 +525,7 @@ static void fix_point_heights( TGConstruct& c, const TGArray& array )
raw_nodes[n1].setz( min );
raw_nodes[n2].setz( min );
raw_nodes[n3].setz( min );
} else if ( (a == StreamArea) || (a == IntStreamArea)
|| (a == CanalArea) ) {
} else if ( is_stream_area( a ) ) {
e1 = raw_nodes[n1].z();
e2 = raw_nodes[n2].z();
e3 = raw_nodes[n3].z();
@ -546,8 +545,7 @@ static void fix_point_heights( TGConstruct& c, const TGArray& array )
if ( max1 < e1 ) { raw_nodes[n1].setz( max1 ); }
if ( max2 < e2 ) { raw_nodes[n2].setz( max2 ); }
if ( max3 < e3 ) { raw_nodes[n3].setz( max3 ); }
} else if ( (a == RoadArea) || (a == FreewayArea)
|| (a == RailroadArea) ) {
} else if ( is_road_area( a ) ) {
e1 = raw_nodes[n1].z();
e2 = raw_nodes[n2].z();
e3 = raw_nodes[n3].z();
@ -581,7 +579,7 @@ static void fix_point_heights( TGConstruct& c, const TGArray& array )
n3 = t.get_n3();
a = (AreaType)((int)(t.get_attribute()));
if ( a == OceanArea ) {
if ( is_ocean_area( a ) ) {
raw_nodes[n1].setz( 0.0 );
raw_nodes[n2].setz( 0.0 );
raw_nodes[n3].setz( 0.0 );
@ -611,7 +609,7 @@ static void fix_land_cover_assignments( TGConstruct& c ) {
cout << " Total triangles = " << tri_elements.size() << endl;
for ( unsigned int i = 0; i < tri_elements.size(); ++i ) {
TGTriEle t = tri_elements[i];
if ( t.get_attribute() == DefaultArea ) {
if ( t.get_attribute() == get_default_area_type() ) {
Point3D p1 = geod_nodes[t.get_n1()];
Point3D p2 = geod_nodes[t.get_n2()];
Point3D p3 = geod_nodes[t.get_n3()];
@ -1043,6 +1041,7 @@ static void usage( const string name ) {
cout << " --xdist=<degrees>" << endl;
cout << " --ydist=<degrees>" << endl;
cout << " --nudge=<float>" << endl;
cout << " --priorities=<filename>" << endl;
cout << " --usgs-map=<filename>" << endl;
cout << " --useUKgrid" << endl;
cout << " --no-write-shared-edges" << endl;
@ -1056,6 +1055,7 @@ int main(int argc, char **argv) {
string output_dir = ".";
string work_dir = ".";
string cover = "";
string priorities_file = DEFAULT_PRIORITIES_FILE;
string usgs_map_file = DEFAULT_USGS_MAPFILE;
double lon = -110.664244; // P13
double lat = 33.352890;
@ -1102,6 +1102,8 @@ int main(int argc, char **argv) {
nudge = atof(arg.substr(8).c_str())*SG_EPSILON;
} else if (arg.find("--cover=") == 0) {
cover = arg.substr(8);
} else if (arg.find("--priorities=") == 0) {
priorities_file = arg.substr(13);
} else if (arg.find("--usgs-map=") == 0) {
usgs_map_file = arg.substr(11);
} else if (arg.find("--useUKgrid") == 0) {
@ -1132,6 +1134,11 @@ int main(int argc, char **argv) {
load_dirs.push_back(argv[i]);
cout << "Load directory: " << argv[i] << endl;
}
cout << "Priorities file is " << priorities_file << endl;
if ( ! load_area_types( priorities_file ) ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to load priorities file " << priorities_file);
exit(-1);
}
cout << "USGS Map file is " << usgs_map_file << endl;
if ( ! load_usgs_map( usgs_map_file ) ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to load USGS map file " << usgs_map_file);

View file

@ -59,9 +59,9 @@ int load_usgs_map( const std::string& filename ) {
AreaType translateUSGSCover (int usgs_value)
{
if ( 0<usgs_value && usgs_value<usgs_map.size() ) {
return usgs_map[usgs_value];
return usgs_map[usgs_value-1];
} else {
return usgs_map[0];
return get_default_area_type();
}
}

View file

@ -1,5 +1,3 @@
# Default setting
Default
# 1: Urban and Built-Up Land
BuiltUpCover
# 2: Dryland Cropland and Pasture

View file

@ -45,235 +45,235 @@ TGTriangle::~TGTriangle( void ) {
// populate this class based on the specified gpc_polys list
int
TGTriangle::build( const point_list& corner_list,
const point_list& fit_list,
const TGPolyList& gpc_polys )
const point_list& fit_list,
const TGPolyList& gpc_polys )
{
int debug_counter = 0;
int index;
int i;
in_nodes.clear();
in_segs.clear();
// Point3D junkp;
// int junkc = 0;
// FILE *junkfp;
// traverse the array corner and fit lists and gpc_polys building a
// unified node list and converting the polygons so that they
// reference the node list by index (starting at zero) rather than
// listing the points explicitely
// first the corners since these are important
for ( i = 0; i < (int)corner_list.size(); ++i ) {
Point3D p = corner_list[i];
p.setz( -9999.0 );
index = in_nodes.unique_add( p );
index = in_nodes.unique_add( p );
}
// next process the polygons
TGPolygon gpc_poly;
const_poly_list_iterator current, last;
// process polygons in priority order
cout << "prepairing node list and polygons" << endl;
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
polylist[i].clear();
cout << "area type = " << i << " polys = " << gpc_polys.polys[i].size()
<< endl;
debug_counter = 0;
current = gpc_polys.polys[i].begin();
last = gpc_polys.polys[i].end();
for ( ; current != last; ++current ) {
gpc_poly = *current;
cout << "processing a polygon, contours = "
<< gpc_poly.contours() << endl;
if (gpc_poly.contours() <= 0 ) {
cout << "FATAL ERROR! no contours in this polygon" << endl;
exit(-1);
}
int j;
for ( j = 0; j < gpc_poly.contours(); ++j ) {
cout << " processing contour = " << j << ", nodes = "
<< gpc_poly.contour_size( j ) << ", hole = "
<< gpc_poly.get_hole_flag( j ) << endl;
/*
polylist[i].clear();
cout << "area type = " << i << " polys = " << gpc_polys.polys[i].size()
<< endl;
debug_counter = 0;
current = gpc_polys.polys[i].begin();
last = gpc_polys.polys[i].end();
for ( ; current != last; ++current ) {
gpc_poly = *current;
cout << "processing a polygon, contours = "
<< gpc_poly.contours() << endl;
if (gpc_poly.contours() <= 0 ) {
cout << "FATAL ERROR! no contours in this polygon" << endl;
exit(-1);
}
int j;
for ( j = 0; j < gpc_poly.contours(); ++j ) {
cout << " processing contour = " << j << ", nodes = "
<< gpc_poly.contour_size( j ) << ", hole = "
<< gpc_poly.get_hole_flag( j ) << endl;
/*
char junkn[256];
sprintf(junkn, "c%d", j);
gpc_poly.write_contour( j, junkn );
*/
for ( int k = 0; k < gpc_poly.contour_size( j ); k++ ) {
Point3D p = gpc_poly.get_pt( j, k );
index = in_nodes.unique_add( p );
// junkp = in_nodes.get_node( index );
// fprintf(junkfp, "%.4f %.4f\n", junkp.x(), junkp.y());
// cout << " - " << index << endl;
}
// fprintf(junkfp, "%.4f %.4f\n",
// gpc_poly->contour[j].vertex[0].x,
// gpc_poly->contour[j].vertex[0].y);
// fclose(junkfp);
}
/* if ( i == OceanArea ) {
cout << "temporary exit point" << endl;
exit(-1);
} */
// for each contour, calculate a point inside (but not
// also inside any interior contours
// new way
// try to make sure our polygons aren't goofy
#if 0
sprintf(junkn, "c%d", j);
gpc_poly.write_contour( j, junkn );
*/
for ( int k = 0; k < gpc_poly.contour_size( j ); k++ ) {
Point3D p = gpc_poly.get_pt( j, k );
index = in_nodes.unique_add( p );
// junkp = in_nodes.get_node( index );
// fprintf(junkfp, "%.4f %.4f\n", junkp.x(), junkp.y());
// cout << " - " << index << endl;
}
// fprintf(junkfp, "%.4f %.4f\n",
// gpc_poly->contour[j].vertex[0].x,
// gpc_poly->contour[j].vertex[0].y);
// fclose(junkfp);
}
/* if ( i == OceanArea ) {
cout << "temporary exit point" << endl;
exit(-1);
} */
// for each contour, calculate a point inside (but not
// also inside any interior contours
// new way
// try to make sure our polygons aren't goofy
#if 0
// CLO 09/18/2001: if we snap polygons including holes
// will this screw up the edge matching when objects are
// inserted into their holes?
gpc_poly = snap(gpc_poly, 0.000001);
#endif
gpc_poly = remove_dups( gpc_poly );
gpc_poly = reduce_degeneracy( gpc_poly );
gpc_poly = reduce_degeneracy( gpc_poly ); // can happen multiple time
gpc_poly = remove_dups( gpc_poly );
gpc_poly = remove_bad_contours( gpc_poly );
gpc_poly = remove_cycles( gpc_poly );
cout << "after sanity checks, contours = "
<< gpc_poly.contours() << endl;
/*
gpc_poly = snap(gpc_poly, 0.000001);
#endif
gpc_poly = remove_dups( gpc_poly );
gpc_poly = reduce_degeneracy( gpc_poly );
gpc_poly = reduce_degeneracy( gpc_poly ); // can happen multiple time
gpc_poly = remove_dups( gpc_poly );
gpc_poly = remove_bad_contours( gpc_poly );
gpc_poly = remove_cycles( gpc_poly );
cout << "after sanity checks, contours = "
<< gpc_poly.contours() << endl;
/*
for ( j = 0; j < gpc_poly.contours(); ++j ) {
cout << " contour " << j << " size = "
<< gpc_poly.contour_size( j ) << endl;
char junkn[256];
sprintf(junkn, "d%d", j);
gpc_poly.write_contour( j, junkn );
cout << " contour " << j << " size = "
<< gpc_poly.contour_size( j ) << endl;
char junkn[256];
sprintf(junkn, "d%d", j);
gpc_poly.write_contour( j, junkn );
}
*/
cout << "before calc_points_inside()" << endl;
calc_points_inside( gpc_poly );
cout << "after calc_points_inside()" << endl;
#if 0
// old way
Point3D inside_pt;
for ( j = 0; j < gpc_poly.contours(); ++j ) {
inside_pt = calc_point_inside( gpc_poly, j, in_nodes );
gpc_poly.set_point_inside( j, inside_pt );
}
#endif
polylist[i].push_back( gpc_poly );
#if 0
// temporary ... write out hole/polygon info for debugging
for ( j = 0; j < (int)gpc_poly.contours(); ++j ) {
char pname[256];
sprintf(pname, "poly%02d-%02d-%02d", i, debug_counter, j);
cout << "writing to " << pname << endl;
FILE *fp = fopen( pname, "w" );
Point3D point;
for ( int k = 0; k < gpc_poly.contour_size( j ); ++k ) {
point = gpc_poly.get_pt( j, k );
fprintf( fp, "%.6f %.6f\n", point.x(), point.y() );
}
point = gpc_poly.get_pt( j, 0 );
fprintf( fp, "%.6f %.6f\n", point.x(), point.y() );
fclose(fp);
char hname[256];
sprintf(hname, "hole%02d-%02d-%02d", i, debug_counter, j);
FILE *fh = fopen( hname, "w" );
point = gpc_poly.get_point_inside( j );
fprintf( fh, "%.6f %.6f\n", point.x(), point.y() );
fclose(fh);
}
// cout << "type a letter + enter to continue: ";
// string input;
// cin >> input;
#endif
++debug_counter;
}
*/
cout << "before calc_points_inside()" << endl;
calc_points_inside( gpc_poly );
cout << "after calc_points_inside()" << endl;
#if 0
// old way
Point3D inside_pt;
for ( j = 0; j < gpc_poly.contours(); ++j ) {
inside_pt = calc_point_inside( gpc_poly, j, in_nodes );
gpc_poly.set_point_inside( j, inside_pt );
}
#endif
polylist[i].push_back( gpc_poly );
#if 0
// temporary ... write out hole/polygon info for debugging
for ( j = 0; j < (int)gpc_poly.contours(); ++j ) {
char pname[256];
sprintf(pname, "poly%02d-%02d-%02d", i, debug_counter, j);
cout << "writing to " << pname << endl;
FILE *fp = fopen( pname, "w" );
Point3D point;
for ( int k = 0; k < gpc_poly.contour_size( j ); ++k ) {
point = gpc_poly.get_pt( j, k );
fprintf( fp, "%.6f %.6f\n", point.x(), point.y() );
}
point = gpc_poly.get_pt( j, 0 );
fprintf( fp, "%.6f %.6f\n", point.x(), point.y() );
fclose(fp);
char hname[256];
sprintf(hname, "hole%02d-%02d-%02d", i, debug_counter, j);
FILE *fh = fopen( hname, "w" );
point = gpc_poly.get_point_inside( j );
fprintf( fh, "%.6f %.6f\n", point.x(), point.y() );
fclose(fh);
}
// cout << "type a letter + enter to continue: ";
// string input;
// cin >> input;
#endif
++debug_counter;
}
}
// last, do the rest of the height nodes
for ( i = 0; i < (int)fit_list.size(); ++i ) {
index = in_nodes.course_add( fit_list[i] );
index = in_nodes.course_add( fit_list[i] );
}
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
if ( polylist[i].size() ) {
cout << get_area_name((AreaType)i) << " = "
<< polylist[i].size() << endl;
}
if ( polylist[i].size() ) {
cout << get_area_name((AreaType)i) << " = "
<< polylist[i].size() << endl;
}
}
// traverse the polygon lists and build the segment (edge) list
// that is used by the "Triangle" lib.
cout << "building segment list" << endl;
int i1, i2;
Point3D p1, p2;
point_list node_list = in_nodes.get_node_list();
TGPolygon poly;
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
cout << "area type = " << i << endl;
poly_list_iterator tp_current, tp_last;
tp_current = polylist[i].begin();
tp_last = polylist[i].end();
// process each polygon in list
for ( ; tp_current != tp_last; ++tp_current ) {
poly = *tp_current;
cout << " processing a polygon with contours = "
<< poly.contours() << endl;
for ( int j = 0; j < (int)poly.contours(); ++j) {
for ( int k = 0; k < (int)(poly.contour_size(j) - 1); ++k ) {
p1 = poly.get_pt( j, k );
p2 = poly.get_pt( j, k + 1 );
i1 = in_nodes.find( p1 );
i2 = in_nodes.find( p2 );
// calc_line_params(i1, i2, &m, &b);
if ( i == (int)HoleArea ) {
// mark as a boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 1) );
} else {
// non boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 0) );
}
}
p1 = poly.get_pt( j, 0 );
p2 = poly.get_pt( j, poly.contour_size(j) - 1 );
i1 = in_nodes.find( p1 );
i2 = in_nodes.find( p2 );
// calc_line_params(i1, i2, &m, &b);
if ( i == (int)HoleArea ) {
// mark as a boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 1) );
} else {
// non boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 0) );
}
}
}
cout << "area type = " << i << endl;
poly_list_iterator tp_current, tp_last;
tp_current = polylist[i].begin();
tp_last = polylist[i].end();
// process each polygon in list
for ( ; tp_current != tp_last; ++tp_current ) {
poly = *tp_current;
cout << " processing a polygon with contours = "
<< poly.contours() << endl;
for ( int j = 0; j < (int)poly.contours(); ++j) {
for ( int k = 0; k < (int)(poly.contour_size(j) - 1); ++k ) {
p1 = poly.get_pt( j, k );
p2 = poly.get_pt( j, k + 1 );
i1 = in_nodes.find( p1 );
i2 = in_nodes.find( p2 );
// calc_line_params(i1, i2, &m, &b);
if ( is_hole_area(i) ) {
// mark as a boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 1) );
} else {
// non boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 0) );
}
}
p1 = poly.get_pt( j, 0 );
p2 = poly.get_pt( j, poly.contour_size(j) - 1 );
i1 = in_nodes.find( p1 );
i2 = in_nodes.find( p2 );
// calc_line_params(i1, i2, &m, &b);
if ( is_hole_area(i) ) {
// mark as a boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 1) );
} else {
// non boundary
in_segs.unique_divide_and_add( node_list,
TGTriSeg(i1, i2, 0) );
}
}
}
}
return 0;
}
@ -282,10 +282,10 @@ TGTriangle::build( const point_list& corner_list,
int TGTriangle::rebuild( TGConstruct& c ) {
in_nodes.clear();
in_segs.clear();
in_nodes = c.get_tri_nodes();
in_segs = c.get_tri_segs();
return 0;
}
@ -303,118 +303,126 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
struct triangulateio in, out, vorout;
int counter;
int i, j;
// point list
point_list node_list = in_nodes.get_node_list();
in.numberofpoints = node_list.size();
in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
for ( i = 0; i < in.numberofpoints; ++i ) {
in.pointlist[2*i] = node_list[i].x();
in.pointlist[2*i + 1] = node_list[i].y();
in.pointlist[2*i] = node_list[i].x();
in.pointlist[2*i + 1] = node_list[i].y();
}
in.numberofpointattributes = 1;
in.pointattributelist = (REAL *) malloc(in.numberofpoints *
in.numberofpointattributes *
sizeof(REAL));
in.numberofpointattributes *
sizeof(REAL));
for ( i = 0; i < in.numberofpoints * in.numberofpointattributes; ++i) {
in.pointattributelist[i] = node_list[i].z();
in.pointattributelist[i] = node_list[i].z();
}
in.pointmarkerlist = (int *) malloc(in.numberofpoints * sizeof(int));
for ( i = 0; i < in.numberofpoints; ++i) {
in.pointmarkerlist[i] = 0;
in.pointmarkerlist[i] = 0;
}
// triangle list
in.numberoftriangles = 0;
// segment list
triseg_list seg_list = in_segs.get_seg_list();
in.numberofsegments = seg_list.size();
in.segmentlist = (int *) malloc(in.numberofsegments * 2 * sizeof(int));
in.segmentmarkerlist = (int *) malloc(in.numberofsegments * sizeof(int));
triseg_list_iterator s_current, s_last;
s_current = seg_list.begin();
s_last = seg_list.end();
counter = 0;
for ( ; s_current != s_last; ++s_current ) {
in.segmentlist[counter++] = s_current->get_n1();
in.segmentlist[counter++] = s_current->get_n2();
in.segmentlist[counter++] = s_current->get_n1();
in.segmentlist[counter++] = s_current->get_n2();
}
s_current = seg_list.begin();
s_last = seg_list.end();
counter = 0;
for ( ; s_current != s_last; ++s_current ) {
in.segmentmarkerlist[counter++] = s_current->get_boundary_marker();
in.segmentmarkerlist[counter++] = s_current->get_boundary_marker();
}
// hole list (make holes for airport ignore areas)
poly_list_iterator h_current, h_last;
in.numberofholes = 0;
h_current = polylist[(int)HoleArea].begin();
h_last = polylist[(int)HoleArea].end();
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
in.numberofholes++;
for ( i = 0; i < TG_MAX_AREA_TYPES; i++) {
if ( is_hole_area( i ) ) {
h_current = polylist[i].begin();
h_last = polylist[i].end();
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
in.numberofholes++;
}
}
}
}
in.holelist = (REAL *) malloc(in.numberofholes * 2 * sizeof(REAL));
h_current = polylist[(int)HoleArea].begin();
h_last = polylist[(int)HoleArea].end();
counter = 0;
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
p = poly.get_point_inside( j );
in.holelist[counter++] = p.x();
in.holelist[counter++] = p.y();
}
for ( i = 0; i < TG_MAX_AREA_TYPES; i++) {
if ( is_hole_area( i ) ) {
h_current = polylist[i].begin();
h_last = polylist[i].end();
counter = 0;
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
p = poly.get_point_inside( j );
in.holelist[counter++] = p.x();
in.holelist[counter++] = p.y();
}
}
}
}
// region list
in.numberofregions = 0;
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
poly_list_iterator h_current, h_last;
h_current = polylist[i].begin();
h_last = polylist[i].end();
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
if ( ! poly.get_hole_flag( j ) ) {
++in.numberofregions;
}
}
}
poly_list_iterator h_current, h_last;
h_current = polylist[i].begin();
h_last = polylist[i].end();
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
if ( ! poly.get_hole_flag( j ) ) {
++in.numberofregions;
}
}
}
}
in.regionlist = (REAL *) malloc(in.numberofregions * 4 * sizeof(REAL));
counter = 0;
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
poly_list_iterator h_current, h_last;
h_current = polylist[(int)i].begin();
h_last = polylist[(int)i].end();
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
if ( ! poly.get_hole_flag( j ) ) {
p = poly.get_point_inside( j );
cout << "Region point = " << p << endl;
in.regionlist[counter++] = p.x(); // x coord
in.regionlist[counter++] = p.y(); // y coord
in.regionlist[counter++] = i; // region attribute
in.regionlist[counter++] = -1.0; // area constraint
// (unused)
}
}
}
poly_list_iterator h_current, h_last;
h_current = polylist[(int)i].begin();
h_last = polylist[(int)i].end();
for ( ; h_current != h_last; ++h_current ) {
poly = *h_current;
for ( j = 0; j < poly.contours(); ++j ) {
if ( ! poly.get_hole_flag( j ) ) {
p = poly.get_point_inside( j );
cout << "Region point = " << p << endl;
in.regionlist[counter++] = p.x(); // x coord
in.regionlist[counter++] = p.y(); // y coord
in.regionlist[counter++] = i; // region attribute
in.regionlist[counter++] = -1.0; // area constraint
// (unused)
}
}
}
}
// prep the output structures
out.pointlist = (REAL *) NULL; // Not needed if -N switch used.
// Not needed if -N switch used or number of point attributes is zero:
@ -430,7 +438,7 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
out.segmentmarkerlist = (int *) NULL;
out.edgelist = (int *) NULL; // Needed only if -e switch used.
out.edgemarkerlist = (int *) NULL; // Needed if -e used and -B not used.
vorout.pointlist = (REAL *) NULL; // Needed only if -v switch used.
// Needed only if -v switch used and number of attributes is not zero:
vorout.pointattributelist = (REAL *) NULL;
@ -439,81 +447,81 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
// TEMPORARY
// write_tri_data(&in); exit(1);
// Triangulate the points. Switches are chosen to read and write
// a PSLG (p), preserve the convex hull (c), number everything
// from zero (z), assign a regional attribute to each element (A),
// and produce an edge list (e), and a triangle neighbor list (n).
string tri_options;
if ( pass == 1 ) {
// use a quality value of 10 (q10) meaning no interior
// triangle angles less than 10 degrees
// tri_options = "pczAen";
if ( angle < 0.00001 ) {
tri_options = "pczAen";
} else {
// use a quality value of 10 (q10) meaning no interior
// triangle angles less than 10 degrees
// tri_options = "pczAen";
if ( angle < 0.00001 ) {
tri_options = "pczAen";
} else {
char angle_str[256];
sprintf( angle_str, "%.2f", angle );
tri_options = "pczq";
tri_options = "pczq";
tri_options += angle_str;
tri_options += "Aen";
}
// // string tri_options = "pzAen";
// // string tri_options = "pczq15S400Aen";
}
// // string tri_options = "pzAen";
// // string tri_options = "pczq15S400Aen";
} else if ( pass == 2 ) {
// no new points on boundary (Y), no internal segment
// splitting (YY), no quality refinement (q)
tri_options = "pczYYAen";
// no new points on boundary (Y), no internal segment
// splitting (YY), no quality refinement (q)
tri_options = "pczYYAen";
} else {
cout << "unknown pass number = " << pass
<< " in TGTriangle::run_triangulate()" << endl;
exit(-1);
cout << "unknown pass number = " << pass
<< " in TGTriangle::run_triangulate()" << endl;
exit(-1);
}
cout << "Triangulation with options = " << tri_options << endl;
triangulate( (char *)tri_options.c_str(), &in, &out, &vorout );
// TEMPORARY
// write_tri_data(&out);
// now copy the results back into the corresponding TGTriangle
// structures
// nodes
out_nodes.clear();
for ( i = 0; i < out.numberofpoints; ++i ) {
Point3D p( out.pointlist[2*i], out.pointlist[2*i + 1],
out.pointattributelist[i] );
out_nodes.simple_add( p );
Point3D p( out.pointlist[2*i], out.pointlist[2*i + 1],
out.pointattributelist[i] );
out_nodes.simple_add( p );
}
// segments
out_segs.clear();
for ( i = 0; i < out.numberofsegments; ++i ) {
out_segs.unique_add( TGTriSeg( out.segmentlist[2*i],
out.segmentlist[2*i+1],
out.segmentmarkerlist[i] ) );
out_segs.unique_add( TGTriSeg( out.segmentlist[2*i],
out.segmentlist[2*i+1],
out.segmentmarkerlist[i] ) );
}
// triangles
elelist.clear();
int n1, n2, n3;
double attribute;
for ( i = 0; i < out.numberoftriangles; ++i ) {
n1 = out.trianglelist[i * 3];
n2 = out.trianglelist[i * 3 + 1];
n3 = out.trianglelist[i * 3 + 2];
if ( out.numberoftriangleattributes > 0 ) {
attribute = out.triangleattributelist[i];
} else {
attribute = 0.0;
}
// cout << "triangle = " << n1 << " " << n2 << " " << n3 << endl;
elelist.push_back( TGTriEle( n1, n2, n3, attribute ) );
n1 = out.trianglelist[i * 3];
n2 = out.trianglelist[i * 3 + 1];
n3 = out.trianglelist[i * 3 + 2];
if ( out.numberoftriangleattributes > 0 ) {
attribute = out.triangleattributelist[i];
} else {
attribute = 0.0;
}
// cout << "triangle = " << n1 << " " << n2 << " " << n3 << endl;
elelist.push_back( TGTriEle( n1, n2, n3, attribute ) );
}
// free mem allocated to the "Triangle" structures
free(in.pointlist);
free(in.pointattributelist);
@ -534,7 +542,7 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
free(vorout.pointattributelist);
free(vorout.edgelist);
free(vorout.normlist);
return 0;
}