1
0
Fork 0

Checkpoint 2

- fixed tile matching using add_intermediate_nodes
- source code rearrangement phase 1 - remove a lot of libraries that are not used by other apps
- move some of the Buildtiles libraries that are used by other apps (and libs) into terragear lib directory
- debug message overhal - to show some progress.
TODO - not implemented yet
- caculate face nodes and save in superpoly (where the faces are stored)
- calculate node normals, and store in tg_nodes (where the nodes are stored)
TODO - bugs
- find_intermediate_nodes isn't working for a lot of roads - still many t-juntions making visible gaps
- flatten ocean nosed is also creating gaps
- there's a grey poly on madeira - need to investigate
This commit is contained in:
Peter Sadrozinski 2012-07-14 14:32:46 -04:00 committed by Christian Schmitt
parent e6ac493395
commit ffc9db1b82
35 changed files with 1799 additions and 3742 deletions

View file

@ -50,13 +50,13 @@
#include <Geometry/poly_support.hxx>
#include <Geometry/poly_extra.hxx>
#include <Geometry/trinodes.hxx>
#include <Geometry/trieles.hxx>
#include <Output/output.hxx>
#include <Polygon/chop.hxx>
#include <Polygon/index.hxx>
#include <Polygon/polygon.hxx>
#include <Polygon/superpoly.hxx>
#include <Polygon/texparams.hxx>
#include <Triangulate/trieles.hxx>
#include "apt_surface.hxx"
#include "convex_hull.hxx"

View file

@ -36,7 +36,7 @@ using std::string;
struct sections
{
const char* tex;
int size;
double size;
};
// UK Precision runway sections from after the designation number

View file

@ -4,9 +4,6 @@ include_directories(${PROJECT_SOURCE_DIR}/src/Lib)
include_directories(${PROJECT_SOURCE_DIR}/src/BuildTiles)
add_subdirectory(Osgb36)
add_subdirectory(Parallel)
add_subdirectory(Triangulate)
add_subdirectory(Clipper)
add_subdirectory(GenOutput)
add_subdirectory(Parallel)
add_subdirectory(Match)
add_subdirectory(Main)

View file

@ -1 +0,0 @@
testclipper

View file

@ -1,15 +0,0 @@
add_library(Clipper STATIC
clipper.cxx clipper.hxx priorities.cxx priorities.hxx
)
add_executable(testclipper testclipper.cxx)
target_link_libraries(testclipper
Clipper Osgb36 Triangulate Polygon Geometry
${SIMGEAR_CORE_LIBRARIES}
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
${GPC_LIBRARY})
INSTALL(FILES default_priorities.txt DESTINATION ${PKGDATADIR} )

View file

@ -1,567 +0,0 @@
// clipper.cxx -- top level routines to take a series of arbitrary areas and
// produce a tight fitting puzzle pieces that combine to make a
// tile
//
// Written by Curtis Olson, started February 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: clipper.cxx,v 1.33 2006-11-29 22:19:33 curt Exp $
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
#include <Clipper/priorities.hxx>
#include <Osgb36/osgb36.hxx>
#include "clipper.hxx"
#include <iostream>
#include <stdlib.h>
using std::string;
#define MASK_CLIP 1
// Constructor.
TGClipper::TGClipper():
nudge(0.0),
m_ignore_landmass(false)
{
}
// Destructor.
TGClipper::~TGClipper() {
}
// Initialize the clipper (empty all the polygon buckets.)
bool TGClipper::init() {
for ( int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
polys_in.superpolys[i].clear();
}
nodes.clear();
return true;
}
// Load a polygon definition file.
bool TGClipper::load_polys(const string& path) {
bool poly3d = false;
string first_line;
string poly_name;
AreaType poly_type;
int contours, count, i, j;
int hole_flag;
double startx, starty, startz, x, y, z, lastx, lasty, lastz;
SG_LOG( SG_CLIPPER, SG_INFO, "Loading " << path << " ..." );
sg_gzifstream in( path );
if ( !in ) {
SG_LOG( SG_CLIPPER, SG_ALERT, "Cannot open file: " << path );
exit(-1);
}
TGPolygon poly;
Point3D p;
// (this could break things, why is it here) in >> skipcomment;
while ( !in.eof() ) {
in >> first_line;
if ( first_line == "#2D" ) {
poly3d = false;
in >> poly_name;
} else if ( first_line == "#3D" ) {
poly3d = true;
in >> poly_name;
} else {
// support old format (default to 2d)
poly3d = false;
poly_name = first_line;
}
SG_LOG( SG_CLIPPER, SG_INFO, "poly name = " << poly_name);
poly_type = get_area_type( poly_name );
SG_LOG( SG_CLIPPER, SG_INFO, "poly type (int) = " << (int)poly_type);
in >> contours;
SG_LOG( SG_CLIPPER, SG_INFO, "num contours = " << contours);
poly.erase();
for ( i = 0; i < contours; ++i ) {
in >> count;
if ( count < 3 ) {
SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon with less than 3 data points." );
exit(-1);
}
in >> hole_flag;
in >> startx;
in >> starty;
if ( poly3d ) {
in >> startz;
} else {
startz = -9999.0;
}
p = Point3D(startx+nudge, starty+nudge, startz);
poly.add_node( i, p );
if ( poly3d ) {
nodes.unique_add_fixed_elevation( p );
} else {
nodes.unique_add( p );
}
for ( j = 1; j < count - 1; ++j ) {
in >> x;
in >> y;
if ( poly3d ) {
in >> z;
} else {
z = -9999.0;
}
p = Point3D( x+nudge, y+nudge, z );
poly.add_node( i, p );
if ( poly3d ) {
nodes.unique_add_fixed_elevation( p );
} else {
nodes.unique_add( p );
}
}
in >> lastx;
in >> lasty;
if ( poly3d ) {
in >> lastz;
} else {
lastz = -9999.0;
}
if ( (fabs(startx - lastx) < SG_EPSILON) &&
(fabs(starty - lasty) < SG_EPSILON) &&
(fabs(startz - lastz) < SG_EPSILON) ) {
// last point same as first, discard
} else {
p = Point3D( lastx+nudge, lasty+nudge, lastz );
poly.add_node( i, p );
if ( poly3d ) {
nodes.unique_add_fixed_elevation( p );
} else {
nodes.unique_add( p );
}
}
}
int area = (int)poly_type;
string material = get_area_name( area );
add_poly(area, poly, material);
in >> skipcomment;
}
return true;
}
// Load a polygon definition file containing osgb36 Eastings and Northings
// and convert them to WGS84 Latitude and Longitude
bool TGClipper::load_osgb36_polys(const string& path) {
string poly_name;
AreaType poly_type;
int contours, count, i, j;
int hole_flag;
double startx, starty, x, y, lastx, lasty;
SG_LOG( SG_CLIPPER, SG_INFO, "Loading " << path << " ..." );
sg_gzifstream in( path );
if ( !in ) {
SG_LOG( SG_CLIPPER, SG_ALERT, "Cannot open file: " << path );
exit(-1);
}
TGPolygon poly;
Point3D p;
Point3D OSRef;
in >> skipcomment;
while ( !in.eof() ) {
in >> poly_name;
SG_LOG( SG_CLIPPER, SG_INFO, "poly name = " << poly_name);
poly_type = get_area_type( poly_name );
SG_LOG( SG_CLIPPER, SG_INFO, "poly type (int) = " << (int)poly_type);
in >> contours;
SG_LOG( SG_CLIPPER, SG_INFO, "num contours = " << contours);
poly.erase();
for ( i = 0; i < contours; ++i ) {
in >> count;
if ( count < 3 ) {
SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon with less than 3 data points." );
exit(-1);
}
in >> hole_flag;
in >> startx;
in >> starty;
OSRef = Point3D(startx, starty, -9999.0);
//Convert from OSGB36 Eastings/Northings to WGS84 Lat/Lon
//Note that startx and starty themselves must not be altered since we compare them with unaltered lastx and lasty later
p = OSGB36ToWGS84(OSRef);
poly.add_node( i, p );
nodes.unique_add( p );
SG_LOG( SG_CLIPPER, SG_BULK, "0 = " << startx << ", " << starty );
for ( j = 1; j < count - 1; ++j ) {
in >> x;
in >> y;
OSRef = Point3D( x, y, -9999.0 );
p = OSGB36ToWGS84(OSRef);
poly.add_node( i, p );
nodes.unique_add( p );
SG_LOG( SG_CLIPPER, SG_BULK, j << " = " << x << ", " << y );
}
in >> lastx;
in >> lasty;
if ( (fabs(startx - lastx) < SG_EPSILON) &&
(fabs(starty - lasty) < SG_EPSILON) ) {
// last point same as first, discard
} else {
OSRef = Point3D( lastx, lasty, -9999.0 );
p = OSGB36ToWGS84(OSRef);
poly.add_node( i, p );
nodes.unique_add( p );
SG_LOG( SG_CLIPPER, SG_BULK, count - 1 << " = " << lastx << ", " << lasty );
}
}
int area = (int)poly_type;
string material = get_area_name( area );
add_poly(area, poly, material);
in >> skipcomment;
}
return true;
}
// Add a polygon to the clipper.
void TGClipper::add_poly( int area, const TGPolygon &poly, string material )
{
TGSuperPoly sp;
if ( area < TG_MAX_AREA_TYPES ) {
sp.set_poly( poly );
sp.set_material( material );
polys_in.superpolys[area].push_back(sp);
} else {
SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon type out of range = " << area);
exit(-1);
}
}
// Move slivers from in polygon to out polygon.
void TGClipper::move_slivers( TGPolygon& in, TGPolygon& out ) {
// traverse each contour of the polygon and attempt to identify
// likely slivers
int i;
out.erase();
double angle_cutoff = 10.0 * SGD_DEGREES_TO_RADIANS;
double area_cutoff = 0.00000008;
double min_angle;
double area;
point_list contour;
int hole_flag;
// process contours in reverse order so deleting a contour doesn't
// foul up our sequence
for ( i = in.contours() - 1; i >= 0; --i ) {
min_angle = in.minangle_contour( i );
area = in.area_contour( i );
if ( ((min_angle < angle_cutoff) && (area < area_cutoff)) ||
( area < area_cutoff / 10.0) ) {
// cout << " WE THINK IT'S A SLIVER!" << endl;
// check if this is a hole
hole_flag = in.get_hole_flag( i );
if ( hole_flag ) {
// just delete/eliminate/remove sliver holes
// cout << "just deleting a sliver hole" << endl;
in.delete_contour( i );
} else {
// move sliver contour to out polygon
contour = in.get_contour( i );
in.delete_contour( i );
out.add_contour( contour, hole_flag );
}
}
}
}
// Attempt to merge slivers into a list of polygons.
//
// For each sliver contour, see if a union with another polygon yields
// a polygon with no increased contours (i.e. the sliver is adjacent
// and can be merged.) If so, replace the clipped polygon with the
// new polygon that has the sliver merged in.
void TGClipper::merge_slivers( TGPolyList& clipped, TGPolygon& slivers ) {
TGPolygon poly, result, sliver;
point_list contour;
int original_contours, result_contours;
bool done;
int area, i, j;
for ( i = 0; i < slivers.contours(); ++i ) {
// cout << "Merging sliver = " << i << endl;
// make the sliver polygon
contour = slivers.get_contour( i );
sliver.erase();
sliver.add_contour( contour, 0 );
done = false;
for ( area = 0; area < TG_MAX_AREA_TYPES && !done; ++area ) {
if ( is_hole_area( area ) ) {
// don't merge a non-hole sliver in with a hole
continue;
}
// cout << " testing area = " << area << " with "
// << clipped.polys[area].size() << " polys" << endl;
for ( j = 0; j < (int)clipped.superpolys[area].size() && !done; ++j ) {
// cout << " polygon = " << j << endl;
poly = clipped.superpolys[area][j].get_poly();
original_contours = poly.contours();
result = tgPolygonUnion( poly, sliver );
result_contours = result.contours();
if ( original_contours == result_contours ) {
// cout << " FOUND a poly to merge the sliver with" << endl;
clipped.superpolys[area][j].set_poly( result );
done = true;
}
}
}
if ( !done ) {
// cout << "no suitable polys found for sliver merge" << endl;
}
}
}
// 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) {
TGPolygon accum, tmp;
TGPolygon slivers, remains;
int i, j;
Point3D p;
SG_LOG( SG_CLIPPER, SG_INFO, "Running master clipper" );
SG_LOG( SG_CLIPPER, SG_INFO, " (" << min.x << "," << min.y << ") (" << max.x << "," << max.y << ")" );
accum.erase();
// set up clipping tile : and remember to add the nodes!
polys_in.safety_base.erase();
p = Point3D(min.x, min.y, -9999.0);
polys_in.safety_base.add_node( 0, p );
nodes.unique_add( p );
p = Point3D(max.x, min.y, -9999.0);
polys_in.safety_base.add_node( 0, p );
nodes.unique_add( p );
p = Point3D(max.x, max.y, -9999.0);
polys_in.safety_base.add_node( 0, p );
nodes.unique_add( p );
p = Point3D(min.x, max.y, -9999.0);
polys_in.safety_base.add_node( 0, p );
nodes.unique_add( p );
// set up land mask, we clip most things to this since it is our
// best representation of land vs. ocean. If we have other less
// accurate data that spills out into the ocean, we want to just
// clip it.
// also set up a mask for all water and islands
TGPolygon land_mask, water_mask, island_mask;
land_mask.erase();
water_mask.erase();
island_mask.erase();
for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) {
if ( is_landmass_area( i ) && !m_ignore_landmass ) {
for ( unsigned int j = 0; j < polys_in.superpolys[i].size(); ++j ) {
land_mask = tgPolygonUnion( land_mask, polys_in.superpolys[i][j].get_poly() );
}
} else if ( is_water_area( i ) ) {
for (unsigned int j = 0; j < polys_in.superpolys[i].size(); j++) {
water_mask = tgPolygonUnion( water_mask, polys_in.superpolys[i][j].get_poly() );
}
} else if ( is_island_area( i ) ) {
for (unsigned int j = 0; j < polys_in.superpolys[i].size(); j++) {
island_mask = tgPolygonUnion( island_mask, polys_in.superpolys[i][j].get_poly() );
}
}
}
// process polygons in priority order
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
SG_LOG( SG_CLIPPER, SG_INFO, "num polys of type (" << i << ") = " << polys_in.superpolys[i].size() );
for( j = 0; j < (int)polys_in.superpolys[i].size(); ++j ) {
TGPolygon current = polys_in.superpolys[i][j].get_poly();
SG_LOG( SG_CLIPPER, SG_INFO, get_area_name( (AreaType)i ) << " = " << current.contours() );
tmp = current;
// if not a hole, clip the area to the land_mask
if ( !m_ignore_landmass && !is_hole_area( i ) ) {
tmp = tgPolygonInt( tmp, land_mask );
}
// Airport areas are limited to existing land mass and
// never override water.
//
// 9/26/2005 - CLO: We are going to add the ability to
// manually define airport areas when the default area
// isn't sufficient. It is clear that it is impossible to
// auto-generate correct airport areas in all cases. For
// now we default to topologically continuous scenery and
// wait for people to submit manual fixes.
//
// if ( i == AirportArea ) {
// tmp = tgPolygonInt( tmp, land_mask );
// tmp = tgPolygonDiff( tmp, water_mask );
// }
// if a water area, cut out potential islands
if ( is_water_area( i ) ) {
// clip against island mask
tmp = tgPolygonDiff( tmp, island_mask );
}
TGPolygon result_union, result_diff;
if ( accum.contours() == 0 ) {
result_diff = tmp;
result_union = tmp;
} else {
result_diff = tgPolygonDiff( tmp, accum);
result_union = tgPolygonUnion( tmp, accum);
}
// only add to output list if the clip left us with a polygon
if ( result_diff.contours() > 0 ) {
// move slivers from result_diff polygon to slivers polygon
move_slivers(result_diff, slivers);
// merge any slivers with previously clipped
// neighboring polygons
if ( slivers.contours() > 0 ) {
merge_slivers(polys_clipped, slivers);
}
// add the sliverless result polygon (from after the
// move_slivers) to the clipped polys list
if ( result_diff.contours() > 0 ) {
TGSuperPoly sp;
string material = get_area_name( (AreaType)i );
sp.set_material( material );
sp.set_poly( result_diff );
polys_clipped.superpolys[i].push_back( sp );
}
}
accum = result_union;
}
}
// finally, what ever is left over goes to ocean
// clip to accum against original base tile
// remains = new gpc_polygon;
// remains->num_contours = 0;
// remains->contour = NULL;
remains = tgPolygonDiff( polys_in.safety_base, accum );
if ( remains.contours() > 0 ) {
// cout << "remains contours = " << remains.contours() << endl;
// move slivers from remains polygon to slivers polygon
move_slivers(remains, slivers);
// cout << " After sliver move:" << endl;
// cout << " remains = " << remains.contours() << endl;
// cout << " slivers = " << slivers.contours() << endl;
// merge any slivers with previously clipped
// neighboring polygons
if ( slivers.contours() > 0 ) {
merge_slivers(polys_clipped, slivers);
}
if ( remains.contours() > 0 ) {
TGSuperPoly sp;
string material = get_area_name(get_sliver_target_area_type());
sp.set_material( material );
sp.set_poly( remains );
polys_clipped.superpolys[(int)get_sliver_target_area_type()].push_back(sp);
}
}
SG_LOG( SG_CLIPPER, SG_INFO, " master clipper finished." );
return true;
}

View file

@ -1,127 +0,0 @@
// clipper.hxx -- top level routines to take a series of arbitrary areas and
// produce a tight fitting puzzle pieces that combine to make a
// tile
//
// Written by Curtis Olson, started February 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: clipper.hxx,v 1.11 2007-08-15 14:36:52 curt Exp $
#ifndef _CLIPPER_HXX
#define _CLIPPER_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h>
//#include <Geometry/trinodes.hxx>
#include <Geometry/tg_nodes.hxx>
#include <Polygon/superpoly.hxx>
#include <Polygon/texparams.hxx>
#include <Polygon/point2d.hxx>
#include <string>
#define TG_MAX_AREA_TYPES 128 // FIXME also defined in
// MergerClipper/clipper.hxx
#define EXTRA_SAFETY_CLIP
class TGPolyList
{
public:
superpoly_list superpolys[TG_MAX_AREA_TYPES];
texparams_list texparams[TG_MAX_AREA_TYPES];
TGPolygon safety_base;
};
class TGClipper
{
private:
TGPolyList polys_in, polys_clipped;
//TGTriNodes fixed_elevations;
TGNodes nodes;
public:
// Constructor.
TGClipper (void);
// Destructor.
~TGClipper (void);
// Initialize Clipper (allocate and/or connect structures.)
bool init();
// Load a polygon definition file
bool load_polys(const std::string& path);
// Load an Osgb36 polygon definition file
bool load_osgb36_polys(const std::string& path);
// Add a polygon.
void add_poly(int area, const TGPolygon &poly, std::string material);
// Remove any slivers from in polygon and move them to out
// polygon.
void move_slivers( TGPolygon& in, TGPolygon& out );
// For each sliver contour, see if a union with another polygon
// yields a polygon with no increased contours (i.e. the sliver is
// adjacent and can be merged.) If so, replace the clipped
// polygon with the new polygon that has the sliver merged in.
void merge_slivers( TGPolyList& clipped, TGPolygon& slivers );
// Do actual clipping work.
bool clip_all(const point2d& min, const point2d& max);
// Return output poly list
inline TGPolyList get_polys_clipped() const { return polys_clipped; }
// Return the fixed elevation points list
inline TGNodes get_nodes() const { return nodes; }
inline node_list get_fixed_elevations_nodes() { return nodes.get_fixed_elevation_nodes(); }
double nudge;
bool ignore_landmass() const {
return m_ignore_landmass;
}
void ignore_landmass(bool b) {
m_ignore_landmass = b;
}
protected:
bool m_ignore_landmass;
};
#endif // _CLIPPER_HXX

View file

@ -1,116 +0,0 @@
// main.cxx -- sample use of the clipper lib
//
// Written by Curtis Olson, started February 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: testclipper.cxx,v 1.7 2004-11-19 22:25:49 curt Exp $
#include <simgear/bucket/newbucket.hxx>
#include <simgear/debug/logstream.hxx>
#include "clipper.hxx"
#include <stdlib.h>
using std::cout;
using std::endl;
using std::string;
int main( int argc, char **argv ) {
point2d global_min, global_max;
sglog().setLogLevels( SG_ALL, SG_DEBUG );
global_min.x = global_min.y = 200;
global_max.y = global_max.x = -200;
TGClipper clipper;
clipper.init();
if ( argc < 2 ) {
SG_LOG( SG_CLIPPER, SG_ALERT, "Usage: " << argv[0]
<< " file1 file2 ..." );
exit(-1);
}
// process all specified polygon files
for ( int i = 1; i < argc; i++ ) {
string full_path = argv[i];
// determine bucket for this polygon
int pos = full_path.rfind("/");
string file_name = full_path.substr(pos + 1);
cout << "file name = " << file_name << endl;
pos = file_name.find(".");
string base_name = file_name.substr(0, pos);
cout << "base_name = " << base_name << endl;
long int index;
sscanf( base_name.c_str(), "%ld", &index);
SGBucket b(index);
cout << "bucket = " << b << endl;
// calculate bucket dimensions
point2d c, min, max;
c.x = b.get_center_lon();
c.y = b.get_center_lat();
double span = b.get_width();
if ( (c.y >= -89.0) && (c.y < 89.0) ) {
min.x = c.x - span / 2.0;
max.x = c.x + span / 2.0;
min.y = c.y - SG_HALF_BUCKET_SPAN;
max.y = c.y + SG_HALF_BUCKET_SPAN;
} else if ( c.y < -89.0) {
min.x = -90.0;
max.x = -89.0;
min.y = -180.0;
max.y = 180.0;
} else if ( c.y >= 89.0) {
min.x = 89.0;
max.x = 90.0;
min.y = -180.0;
max.y = 180.0;
} else {
SG_LOG ( SG_GENERAL, SG_ALERT,
"Out of range latitude in clip_and_write_poly() = "
<< c.y );
}
if ( min.x < global_min.x ) global_min.x = min.x;
if ( min.y < global_min.y ) global_min.y = min.y;
if ( max.x > global_max.x ) global_max.x = max.x;
if ( max.y > global_max.y ) global_max.y = max.y;
// finally, load the polygon(s) from this file
clipper.load_polys( full_path );
}
// do the clipping
clipper.clip_all(global_min, global_max);
SG_LOG( SG_CLIPPER, SG_INFO, "finished main" );
return 0;
}

View file

@ -1,5 +0,0 @@
add_library(GenOutput STATIC
genobj.cxx genobj.hxx
)

View file

@ -1,519 +0,0 @@
// genobj.hxx -- Generate the flight gear "obj" file format from the
// triangle output
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: genobj.cxx,v 1.26 2004-11-19 22:25:49 curt Exp $
#include <time.h>
#include <simgear/compiler.h>
#include <simgear/io/sg_binobj.hxx>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/misc/texcoord.hxx>
#include <simgear/debug/logstream.hxx>
#include <Output/output.hxx>
#include <Clipper/priorities.hxx>
#include <Osgb36/osgbtc.hxx>
#include <Osgb36/uk.hxx>
#include "genobj.hxx"
using std::cout;
using std::endl;
using std::string;
// calculate the global bounding sphere. Center is the center of the
// tile and zero elevation
void TGGenOutput::calc_gbs( TGConstruct& c ) {
point_list wgs84_nodes = c.get_wgs84_nodes();
gbs_center = SGVec3d::fromGeod( c.get_bucket().get_center() );
double dist_squared, radius_squared = 0;
for ( unsigned int i = 0; i < wgs84_nodes.size(); ++i ) {
dist_squared = distSqr(gbs_center, wgs84_nodes[i].toSGVec3d());
if ( dist_squared > radius_squared ) {
radius_squared = dist_squared;
}
}
gbs_radius = sqrt(radius_squared);
}
// build the necessary output structures based on the triangulation
// data
int TGGenOutput::build_fans( TGConstruct& c ) {
// TGTriNodes trinodes = c.get_tri_nodes();
TGNodes* nodes = c.get_nodes();
string tile_id = c.get_bucket().gen_index_str();
// copy the geodetic node list into this class
geod_nodes = nodes->get_geod_nodes();
// copy the triangle list into this class
tri_elements = c.get_tri_elements();
// build the trifan list
cout << "total triangles = " << tri_elements.size() << endl;
TGGenFans f;
// Sort the triangles by area type
// TODO: Need to sort on Material type - going to make the attribute an index
// into an array of texparams / material names
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
triele_list area_tris;
area_tris.erase( area_tris.begin(), area_tris.end() );
const_triele_list_iterator t_current = tri_elements.begin();
const_triele_list_iterator t_last = tri_elements.end();
for ( ; t_current != t_last; ++t_current ) {
if ( t_current->get_attribute() == i ) {
area_tris.push_back( *t_current );
}
}
if ( (int)area_tris.size() > 0 ) {
cout << "generating fans for area = " << i << endl;
primitives[i] = f.greedy_build( area_tris );
}
}
// build the texture coordinate list and make a parallel structure
// to the fan list for pointers into the texture list
cout << "calculating texture coordinates" << endl;
cout << "c.get_useUKGrid() = " << c.get_useUKGrid() << endl;
tex_coords.clear();
std::vector < SGGeod > convGeodNodes;
for ( unsigned int k = 0; k < geod_nodes.size(); k++ ) {
Point3D node = geod_nodes[k];
convGeodNodes.push_back( SGGeod::fromDegM( node.x(), node.y(), node.z() ) );
}
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
// cout << " area = " << i << endl;
for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
SG_LOG( SG_CLIPPER, SG_INFO, tile_id << ": Texturing " << get_area_name( (AreaType)i ) << " primitive " << j+1 << " of " << primitives[i].size() );
SGBucket b = c.get_bucket();
Point3D ourPosition;
ourPosition.setlon(b.get_chunk_lon());
ourPosition.setlat(b.get_chunk_lat());
int_list ti_list;
ti_list.clear();
//dcl - here read the flag to check if we are building UK grid
//If so - check if the bucket is within the UK lat & lon
if( (c.get_useUKGrid()) && (isInUK(ourPosition)) ) {
point_list tp_list;
tp_list = UK_calc_tex_coords( b, geod_nodes, primitives[i][j], 1.0 );
for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
// cout << " tc = " << tp_list[k] << endl;
int index = tex_coords.simple_add( tp_list[k] );
ti_list.push_back( index );
}
} else {
std::vector< SGVec2f > tp_list = sgCalcTexCoords( b, convGeodNodes, primitives[i][j] );
for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
SGVec2f tc = tp_list[k];
// SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc);
int index = tex_coords.simple_add( Point3D( tc.x(), tc.y(), 0 ) );
ti_list.push_back( index );
}
}
textures[i].push_back( ti_list );
}
}
// calculate the global bounding sphere
calc_gbs( c );
cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
return 1;
}
static opt_list tgGenTris( const triele_list tris ) {
triele_list remaining = tris;
opt_list tri_lists;
int_list tri;
tri_lists.clear();
for ( unsigned int i = 0; i < tris.size(); ++i ) {
tri.clear();
tri.push_back( tris[i].get_n1() );
tri.push_back( tris[i].get_n2() );
tri.push_back( tris[i].get_n3() );
tri_lists.push_back( tri );
}
return tri_lists;
}
int TGGenOutput::build_tris( TGConstruct& c ) {
// TGTriNodes trinodes = c.get_tri_nodes();
TGNodes* nodes = c.get_nodes();
string tile_id = c.get_bucket().gen_index_str();
// copy the geodetic node list into this class
geod_nodes = nodes->get_geod_nodes();
// copy the triangle list into this class
tri_elements = c.get_tri_elements();
// build the trifan list
cout << "total triangles = " << tri_elements.size() << endl;
// Sort the triangles by area type
// TODO: Need to sort on Material type - going to make the attribute an index
// into an array of texparams / material names
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
triele_list area_tris;
area_tris.erase( area_tris.begin(), area_tris.end() );
const_triele_list_iterator t_current = tri_elements.begin();
const_triele_list_iterator t_last = tri_elements.end();
for ( ; t_current != t_last; ++t_current ) {
if ( t_current->get_attribute() == i ) {
area_tris.push_back( *t_current );
}
}
if ( area_tris.size() > 0 ) {
cout << "generating tris for area = " << i << endl;
primitives[i] = tgGenTris( area_tris );
}
}
// build the texture coordinate list and make a parallel structure
// to the fan list for pointers into the texture list
cout << "calculating texture coordinates" << endl;
cout << "c.get_useUKGrid() = " << c.get_useUKGrid() << endl;
tex_coords.clear();
std::vector < SGGeod > convGeodNodes;
for ( unsigned int k = 0; k < geod_nodes.size(); k++ ) {
Point3D node = geod_nodes[k];
convGeodNodes.push_back( SGGeod::fromDegM( node.x(), node.y(), node.z() ) );
}
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
// cout << " area = " << i << endl;
for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
SG_LOG( SG_CLIPPER, SG_INFO, tile_id << ": Texturing " << get_area_name( (AreaType)i ) << " primitive " << j+1 << " of " << primitives[i].size() );
SGBucket b = c.get_bucket();
Point3D ourPosition;
ourPosition.setlon(b.get_chunk_lon());
ourPosition.setlat(b.get_chunk_lat());
int_list ti_list;
ti_list.clear();
//dcl - here read the flag to check if we are building UK grid
//If so - check if the bucket is within the UK lat & lon
if( (c.get_useUKGrid()) && (isInUK(ourPosition)) ) {
point_list tp_list;
tp_list = UK_calc_tex_coords( b, geod_nodes, primitives[i][j], 1.0 );
for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
// cout << " tc = " << tp_list[k] << endl;
int index = tex_coords.simple_add( tp_list[k] );
ti_list.push_back( index );
}
} else {
std::vector< SGVec2f > tp_list = sgCalcTexCoords( b, convGeodNodes, primitives[i][j] );
for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
SGVec2f tc = tp_list[k];
// SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc);
int index = tex_coords.simple_add( Point3D( tc.x(), tc.y(), 0 ) );
ti_list.push_back( index );
}
}
textures[i].push_back( ti_list );
}
}
// calculate the global bounding sphere
calc_gbs( c );
cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
return 1;
}
// calculate the bounding sphere for a list of triangle faces
void TGGenOutput::calc_group_bounding_sphere( TGConstruct& c,
const opt_list& primitives,
Point3D *center, double *radius )
{
cout << "calculate group bounding sphere for " << primitives.size() << " primitives." << endl;
point_list wgs84_nodes = c.get_wgs84_nodes();
// generate a list of unique points from the triangle list
TGTriNodes nodes;
const_opt_list_iterator f_current = primitives.begin();
const_opt_list_iterator f_last = primitives.end();
for ( ; f_current != f_last; ++f_current ) {
const_int_list_iterator i_current = f_current->begin();
const_int_list_iterator i_last = f_current->end();
for ( ; i_current != i_last; ++i_current ) {
Point3D p1 = wgs84_nodes[ *i_current ];
nodes.unique_add(p1);
}
}
// find average of point list
*center = Point3D( 0.0 );
point_list points = nodes.get_node_list();
// cout << "found " << points.size() << " unique nodes" << endl;
point_list_iterator p_current = points.begin();
point_list_iterator p_last = points.end();
for ( ; p_current != p_last; ++p_current ) {
*center += *p_current;
}
*center /= points.size();
// find max radius
double dist_squared;
double max_squared = 0;
p_current = points.begin();
p_last = points.end();
for ( ; p_current != p_last; ++p_current ) {
dist_squared = (*center).distance3Dsquared(*p_current);
if ( dist_squared > max_squared ) {
max_squared = dist_squared;
}
}
*radius = sqrt(max_squared);
}
// calculate the bounding sphere for the specified triangle face
void TGGenOutput::calc_bounding_sphere( TGConstruct& c, const TGTriEle& t,
Point3D *center, double *radius )
{
point_list wgs84_nodes = c.get_wgs84_nodes();
*center = Point3D( 0.0 );
Point3D p1 = wgs84_nodes[ t.get_n1() ];
Point3D p2 = wgs84_nodes[ t.get_n2() ];
Point3D p3 = wgs84_nodes[ t.get_n3() ];
*center = p1 + p2 + p3;
*center /= 3;
double dist_squared;
double max_squared = 0;
dist_squared = (*center).distance3Dsquared(p1);
if ( dist_squared > max_squared ) {
max_squared = dist_squared;
}
dist_squared = (*center).distance3Dsquared(p2);
if ( dist_squared > max_squared ) {
max_squared = dist_squared;
}
dist_squared = (*center).distance3Dsquared(p3);
if ( dist_squared > max_squared ) {
max_squared = dist_squared;
}
*radius = sqrt(max_squared);
}
// write out the fgfs scenery file (using fans)
int TGGenOutput::write_fans( TGConstruct &c ) {
// Assemble all the data into the final format
SGBucket b = c.get_bucket();
string base = c.get_output_base();
string name = b.gen_index_str();
name += ".btg";
std::vector< SGVec3d > wgs84_nodes;
for ( unsigned int i = 0; i < c.get_wgs84_nodes().size(); i++ ) {
Point3D node = c.get_wgs84_nodes()[i];
wgs84_nodes.push_back( node.toSGVec3d() );
}
std::vector< SGVec3f > normals;
for ( unsigned int i = 0; i < c.get_point_normals().size(); i++ ) {
Point3D node = c.get_point_normals()[i];
normals.push_back( node.toSGVec3f() );
}
cout << "dumping normals = " << normals.size() << endl;
/* for ( i = 0; i < (int)normals.size(); ++i ) {
Point3D p = normals[i];
printf("vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
} */
std::vector< SGVec2f > texcoords;
for ( unsigned int i = 0; i < tex_coords.get_node_list().size(); i++ ) {
Point3D node = tex_coords.get_node_list()[i];
texcoords.push_back( node.toSGVec2f() );
}
// allocate and initialize triangle group structures
group_list tris_v; group_list tris_tc; string_list tri_materials;
tris_v.clear(); tris_tc.clear(); tri_materials.clear();
group_list strips_v; group_list strips_tc; string_list strip_materials;
strips_v.clear(); strips_tc.clear(); strip_materials.clear();
group_list fans_v; group_list fans_tc; string_list fan_materials;
fans_v.clear(); fans_tc.clear(); fan_materials.clear();
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
if ( primitives[i].size() > 0 ) {
cout << "creating " << primitives[i].size() << " fans of type " << i << endl;
string attr_name = get_area_name( (AreaType)i );
int_list vs, tcs;
for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
vs.clear(); tcs.clear();
for ( unsigned int k = 0; k < primitives[i][j].size(); ++k ) {
vs.push_back( primitives[i][j][k] );
tcs.push_back( textures[i][j][k] );
}
fans_v.push_back( vs );
fans_tc.push_back( tcs );
fan_materials.push_back( attr_name );
}
}
}
SGBinObject obj;
obj.set_gbs_center( gbs_center );
obj.set_gbs_radius( gbs_radius );
obj.set_wgs84_nodes( wgs84_nodes );
obj.set_normals( normals );
obj.set_texcoords( texcoords );
obj.set_tris_v( tris_v );
obj.set_tris_tc( tris_tc );
obj.set_tri_materials( tri_materials );
obj.set_strips_v( strips_v );
obj.set_strips_tc( strips_tc );
obj.set_strip_materials( strip_materials );
obj.set_fans_v( fans_v );
obj.set_fans_tc( fans_tc );
obj.set_fan_materials( fan_materials );
obj.write_bin( base, name, b );
return 1;
}
// write out the fgfs scenery file (using tris)
int TGGenOutput::write_tris( TGConstruct &c ) {
// Assemble all the data into the final format
SGBucket b = c.get_bucket();
string base = c.get_output_base();
string name = b.gen_index_str();
name += ".btg";
std::vector< SGVec3d > wgs84_nodes;
for ( unsigned int i = 0; i < c.get_wgs84_nodes().size(); i++ ) {
Point3D node = c.get_wgs84_nodes()[i];
wgs84_nodes.push_back( node.toSGVec3d() );
}
std::vector< SGVec3f > normals;
for ( unsigned int i = 0; i < c.get_point_normals().size(); i++ ) {
Point3D node = c.get_point_normals()[i];
normals.push_back( node.toSGVec3f() );
}
cout << "dumping normals = " << normals.size() << endl;
/* for ( i = 0; i < (int)normals.size(); ++i ) {
Point3D p = normals[i];
printf("vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
} */
std::vector< SGVec2f > texcoords;
for ( unsigned int i = 0; i < tex_coords.get_node_list().size(); i++ ) {
Point3D node = tex_coords.get_node_list()[i];
texcoords.push_back( node.toSGVec2f() );
}
// allocate and initialize triangle group structures
group_list tris_v; group_list tris_tc; string_list tri_materials;
tris_v.clear(); tris_tc.clear(); tri_materials.clear();
group_list strips_v; group_list strips_tc; string_list strip_materials;
strips_v.clear(); strips_tc.clear(); strip_materials.clear();
group_list fans_v; group_list fans_tc; string_list fan_materials;
fans_v.clear(); fans_tc.clear(); fan_materials.clear();
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
if ( primitives[i].size() > 0 ) {
cout << "creating " << primitives[i].size() << " tris of type " << i << endl;
string attr_name = get_area_name( (AreaType)i );
int_list vs, tcs;
for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
vs.clear(); tcs.clear();
for ( unsigned int k = 0; k < primitives[i][j].size(); ++k ) {
vs.push_back( primitives[i][j][k] );
tcs.push_back( textures[i][j][k] );
}
tris_v.push_back( vs );
tris_tc.push_back( tcs );
tri_materials.push_back( attr_name );
}
}
}
SGBinObject obj;
obj.set_gbs_center( gbs_center );
obj.set_gbs_radius( gbs_radius );
obj.set_wgs84_nodes( wgs84_nodes );
obj.set_normals( normals );
obj.set_texcoords( texcoords );
obj.set_tris_v( tris_v );
obj.set_tris_tc( tris_tc );
obj.set_tri_materials( tri_materials );
obj.set_strips_v( strips_v );
obj.set_strips_tc( strips_tc );
obj.set_strip_materials( strip_materials );
obj.set_fans_v( fans_v );
obj.set_fans_tc( fans_tc );
obj.set_fan_materials( fan_materials );
obj.write_bin( base, name, b );
return 1;
}

View file

@ -1,107 +0,0 @@
// genobj.hxx -- Generate the flight gear "obj" file format from the
// triangle output
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: genobj.hxx,v 1.9 2004-11-19 22:25:49 curt Exp $
#ifndef _GENOBJ_HXX
#define _GENOBJ_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h>
#include <simgear/bucket/newbucket.hxx>
#include <Geometry/point3d.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/sg_types.hxx>
#include <Optimize/genfans.hxx>
#include <Main/construct.hxx>
#include <Triangulate/triangle.hxx>
typedef std::vector < int_list > tex_list;
typedef tex_list::iterator tex_list_iterator;
typedef tex_list::const_iterator const_tex_list_iterator;
class TGGenOutput {
private:
// node list in geodetic coordinates
point_list geod_nodes;
// triangles (by index into point list)
triele_list tri_elements;
// texture coordinates
TGTriNodes tex_coords;
// fan / triangle list
opt_list primitives[TG_MAX_AREA_TYPES];
// textures pointer list
tex_list textures[TG_MAX_AREA_TYPES];
// global bounding sphere
SGVec3d gbs_center;
double gbs_radius;
// calculate the global bounding sphere. Center is the average of
// the points.
void calc_gbs( TGConstruct& c );
// caclulate the bounding sphere for a list of triangle faces
void calc_group_bounding_sphere( TGConstruct& c, const opt_list& fans,
Point3D *center, double *radius );
// caclulate the bounding sphere for the specified triangle face
void calc_bounding_sphere( TGConstruct& c, const TGTriEle& t,
Point3D *center, double *radius );
// traverse the specified fan and attempt to calculate "none
// stretching" texture coordinates
// int_list calc_tex_coords( TGConstruct& c, point_list geod_nodes, int_list fan );
public:
// Constructor && Destructor
inline TGGenOutput() { }
inline ~TGGenOutput() { }
// build the necessary output structures based on the
// triangulation data
int build_fans( TGConstruct& c );
int build_tris( TGConstruct& c );
// write out the fgfs scenery file
int write_fans( TGConstruct &c );
int write_tris( TGConstruct &c );
};
#endif // _GENOBJ_HXX

View file

@ -1,18 +1,22 @@
add_executable(fgfs-construct
construct.cxx construct.hxx
usgs.cxx main.cxx)
construct.cxx
construct.hxx
priorities.cxx
priorities.hxx
usgs.cxx
main.cxx)
set_target_properties(fgfs-construct PROPERTIES
COMPILE_DEFINITIONS
"DEFAULT_USGS_MAPFILE=\"${PKGDATADIR}/usgsmap.txt\";DEFAULT_PRIORITIES_FILE=\"${PKGDATADIR}/default_priorities.txt\"" )
target_link_libraries(fgfs-construct
Clipper GenOutput Osgb36 Triangulate
Osgb36
Match
Polygon Geometry
Array Optimize Output landcover poly2tri
Array Optimize landcover poly2tri
TriangleJRS
${GDAL_LIBRARY}
${SIMGEAR_CORE_LIBRARIES}
@ -20,15 +24,6 @@ target_link_libraries(fgfs-construct
${GPC_LIBRARY})
install(TARGETS fgfs-construct RUNTIME DESTINATION bin)
INSTALL(FILES usgsmap.txt DESTINATION ${PKGDATADIR} )
add_executable(fgfs-master
master.cxx)
target_link_libraries(fgfs-master
${SIMGEAR_CORE_LIBRARIES}
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
)
install(TARGETS fgfs-master RUNTIME DESTINATION bin)
INSTALL(FILES default_priorities.txt DESTINATION ${PKGDATADIR} )

File diff suppressed because it is too large Load diff

View file

@ -31,28 +31,42 @@
#endif
// Maximum nodes per tile
#define TG_MAX_NODES 4000
#include <simgear/compiler.h>
#define TG_MAX_AREA_TYPES 128
#include <string>
#include <vector>
#include <simgear/compiler.h>
#include <simgear/bucket/newbucket.hxx>
#include <simgear/misc/sg_path.hxx>
#include <Array/array.hxx>
#include <Polygon/superpoly.hxx>
#include <Polygon/texparams.hxx>
#include <Geometry/tg_nodes.hxx>
#include <landcover/landcover.hxx>
// TO REMOVE
#include <Geometry/trieles.hxx>
#include <Geometry/trinodes.hxx>
#include <Geometry/trisegs.hxx>
#include <Clipper/priorities.hxx>
// TO REMOVE
#include <Clipper/clipper.hxx>
#include <Triangulate/trieles.hxx>
#include "priorities.hxx"
typedef std::vector < int_list > belongs_to_list;
typedef belongs_to_list::iterator belongs_to_list_iterator;
typedef belongs_to_list::const_iterator belongs_to_list_tripoly_iterator;
class TGPolyList
{
public:
superpoly_list superpolys[TG_MAX_AREA_TYPES];
texparams_list texparams[TG_MAX_AREA_TYPES];
TGPolygon safety_base;
};
class TGConstruct {
@ -65,10 +79,14 @@ private:
std::string work_base;
std::string output_base;
std::vector<std::string> load_dirs;
// flag indicating whether to align texture coords within the UK
// with the UK grid
bool useUKGrid;
double nudge;
// flag indicating whether this is a rebuild and Shared edge
// data should only be used for fitting, but not rewritten
bool writeSharedEdges;
@ -80,39 +98,20 @@ private:
// flag indicating whether to ignore the landmass
bool ignoreLandmass;
// detail level constraints
int min_nodes;
int max_nodes;
// this bucket
SGBucket bucket;
// clipped polygons (gpc format)
TGPolyList clipped_polys;
// Elevation data
TGArray array;
// Fixed elevations (from polygon input data with z values
// pre-specified)
node_list fixed_elevations;
// land class polygons
TGPolyList polys_in;
TGPolyList polys_clipped;
// raw node list (after triangulation)
TGTriNodes tri_nodes;
// All Nodes
TGNodes nodes;
// node list in geodetic coords (with fixed elevation)
point_list geod_nodes;
// node list in cartesian coords (wgs84 model)
point_list wgs84_nodes;
// triangle elements (after triangulation)
triele_list tri_elements;
// edge segments (after triangulation)
TGTriSegments tri_segs;
// for each node, a list of triangle indices that contain this node
belongs_to_list reverse_ele_lookup;
// TODO : Add to superpoly
// face normal list (for flat shading)
point_list face_normals;
@ -124,6 +123,39 @@ public:
// Destructor
~TGConstruct();
void construct_bucket( SGBucket b );
bool load_array();
int load_polys();
bool load_poly(const std::string& path);
bool load_osgb36_poly(const std::string& path);
void add_poly(int area, const TGPolygon &poly, std::string material);
void move_slivers( TGPolygon& in, TGPolygon& out );
void merge_slivers( TGPolyList& clipped, TGPolygon& slivers );
bool clip_all(const point2d& min, const point2d& max);
void add_intermediate_nodes(void);
void clean_clipped_polys(void);
void calc_gc_course_dist( const Point3D& start, const Point3D& dest,
double *course, double *dist );
double distanceSphere( const Point3D p1, const Point3D p2 );
void fix_point_heights();
TGPolygon linear_tex_coords( const TGPolygon& tri, const TGTexParams& tp );
TGPolygon area_tex_coords( const TGPolygon& tri );
int load_landcover ();
void add_to_polys( TGPolygon &accum, const TGPolygon &poly);
double measure_roughness( TGPolygon &poly );
AreaType get_landcover_type (const LandCover &cover, double xpos, double ypos, double dx, double dy);
void make_area( const LandCover &cover, TGPolygon *polys,
double x1, double y1, double x2, double y2,
double half_dx, double half_dy );
void do_custom_objects(void);
// land cover file
inline std::string get_cover () const { return cover; }
inline void set_cover (const std::string &s) { cover = s; }
@ -133,71 +165,29 @@ public:
inline void set_work_base( const std::string s ) { work_base = s; }
inline std::string get_output_base() const { return output_base; }
inline void set_output_base( const std::string s ) { output_base = s; }
inline void set_load_dirs( const std::vector<std::string> ld ) { load_dirs = ld; }
// UK grid flag
inline bool get_useUKGrid() const { return useUKGrid; }
inline void set_useUKGrid( const bool b ) { useUKGrid = b; }
// Nudge
inline void set_nudge( double n ) { nudge = n; }
// shared edge write flag
inline bool get_write_shared_edges() const { return writeSharedEdges; }
inline void set_write_shared_edges( const bool b ) { writeSharedEdges = b; }
// own shared edge use flag
inline bool get_use_own_shared_edges() const { return useOwnSharedEdges; }
inline void set_use_own_shared_edges( const bool b ) { useOwnSharedEdges = b; }
// ignore landmass flag
inline bool get_ignore_landmass() const { return ignoreLandmass; }
inline void set_ignore_landmass( const bool b) { ignoreLandmass = b; }
// detail level constraints
inline int get_min_nodes() const { return min_nodes; }
inline void set_min_nodes( const int n ) { min_nodes = n; }
inline int get_max_nodes() const { return max_nodes; }
inline void set_max_nodes( const int n ) { max_nodes = n; }
// this bucket
inline SGBucket get_bucket() const { return bucket; }
inline void set_bucket( const SGBucket b ) { bucket = b; }
// clipped polygons
inline TGPolyList get_clipped_polys() const { return clipped_polys; }
inline void set_clipped_polys( TGPolyList p ) { clipped_polys = p; }
// Fixed elevations (from polygon input data with z values pre-specified)
inline node_list get_fixed_elevations() const { return nodes.get_fixed_elevation_nodes(); }
// node list (after triangulation) : No need - we won't add nodes....
// inline TGTriNodes get_tri_nodes() const { return tri_nodes; }
// inline void set_tri_nodes( TGTriNodes n ) { tri_nodes = n; }
// TODO : REMOVE
inline TGNodes* get_nodes() { return &nodes; }
inline void set_nodes( TGNodes n ) { nodes = n; }
// triangle elements (after triangulation) : No need - will be in the triangulated polygons
inline triele_list get_tri_elements() const { return tri_elements; }
inline void set_tri_elements( triele_list e ) { tri_elements = e; }
inline void set_tri_attribute( int num, AreaType a ) { tri_elements[num].set_attribute( a ); }
// edge segments (after triangulation) : Same as above
inline TGTriSegments get_tri_segs() const { return tri_segs; }
inline void set_tri_segs( TGTriSegments s ) { tri_segs = s; }
// node list in geodetic coords (with fixed elevation)
inline point_list get_geod_nodes() const { return nodes.get_geod_nodes(); }
// inline void set_geod_nodes( point_list n ) { geod_nodes = n; }
// node list in cartesian coords (wgs84 model)
inline point_list get_wgs84_nodes() const { return nodes.get_wgs84_nodes_as_Point3d(); }
// inline void set_wgs84_nodes( point_list n ) { wgs84_nodes = n; }
// for each node, a list of triangle indices that contain this node
inline belongs_to_list get_reverse_ele_lookup() const {
return reverse_ele_lookup;
}
inline void set_reverse_ele_lookup( belongs_to_list r ) {
reverse_ele_lookup = r;
}
// face normal list (for flat shading)
inline point_list get_face_normals() const { return face_normals; }

View file

@ -7,6 +7,13 @@ Hole hole # Leave area completely empty
Airport other
Freeway road
Road road
Road-Motorway road
Road-Trunk road
Road-Residential road
Road-Primary road
Road-Secondary road
Road-Tertiary road
Railroad road
Asphalt road
Pond lake

File diff suppressed because it is too large Load diff

View file

@ -22,11 +22,11 @@
#ifndef _USGS_HXX
#define _USGS_HXX
#include <Clipper/priorities.hxx>
#include <string>
#include <simgear/compiler.h>
#include <string>
#include "priorities.hxx"
int load_usgs_map( const std::string& filename );
AreaType translateUSGSCover( int usgs_value );

View file

@ -141,14 +141,10 @@ void TGMatch::scan_share_file( const string& dir, const SGBucket& b,
// try to find info for the specified shared component
void TGMatch::load_shared( const TGConstruct& c, neighbor_type n ) {
SGBucket b = c.get_bucket();
void TGMatch::load_shared( SGBucket b, string base, neighbor_type n ) {
double clon = b.get_center_lon();
double clat = b.get_center_lat();
string base = c.get_work_base() + "/Shared/";
SGBucket cb;
if ( n == SW_Corner ) {
@ -205,27 +201,29 @@ void TGMatch::load_shared( const TGConstruct& c, neighbor_type n ) {
// load any previously existing shared data from all neighbors (if
// shared data for a component exists set that components flag to true
void TGMatch::load_neighbor_shared( TGConstruct& c ) {
void TGMatch::load_neighbor_shared( SGBucket b, string work ) {
cout << "Loading existing shared data from neighbor tiles" << endl;
string base = work + "/Shared/";
// start with all flags false
sw_flag = se_flag = ne_flag = nw_flag = false;
north_flag = south_flag = east_flag = west_flag = false;
load_shared( c, SW_Corner );
load_shared( c, SE_Corner );
load_shared( c, NE_Corner );
load_shared( c, NW_Corner );
load_shared( b, base, SW_Corner );
load_shared( b, base, SE_Corner );
load_shared( b, base, NE_Corner );
load_shared( b, base, NW_Corner );
north_nodes.clear();
south_nodes.clear();
east_nodes.clear();
west_nodes.clear();
load_shared( c, NORTH );
load_shared( c, SOUTH );
load_shared( c, EAST );
load_shared( c, WEST );
load_shared( b, base, NORTH );
load_shared( b, base, SOUTH );
load_shared( b, base, EAST );
load_shared( b, base, WEST );
cout << "Shared data read in:" << endl;
if ( sw_flag ) {
@ -271,13 +269,11 @@ void TGMatch::load_neighbor_shared( TGConstruct& c ) {
}
// try to load any missing shared data from our own shared data file
void TGMatch::load_missing_shared( TGConstruct& c ) {
SGBucket b = c.get_bucket();
void TGMatch::load_missing_shared( SGBucket b, string work ) {
double clon = b.get_center_lon();
double clat = b.get_center_lat();
string base = c.get_work_base() + "/Shared/";
string base = work + "/Shared/";
if ( !nw_flag ) {
scan_share_file( base, b, NW_Corner, NW_Corner );
@ -332,7 +328,7 @@ Point3D tgFakeNormal( const Point3D& p ) {
// segments and the body. This must be done after calling
// load_neighbor_data() and will ignore any shared data from the
// current tile that already exists from a neighbor.
void TGMatch::split_tile( TGConstruct& c ) {
void TGMatch::split_tile( SGBucket b, TGConstruct* c ) {
int i;
cout << "Spliting tile" << endl;
@ -340,7 +336,7 @@ void TGMatch::split_tile( TGConstruct& c ) {
// calculate tile boundaries
point2d min, max;
SGBucket b = c.get_bucket();
min.x = b.get_center_lon() - 0.5 * b.get_width();
min.y = b.get_center_lat() - 0.5 * b.get_height();
max.x = b.get_center_lon() + 0.5 * b.get_width();
@ -368,8 +364,8 @@ void TGMatch::split_tile( TGConstruct& c ) {
body_nodes.clear();
point_list nodes = c.get_geod_nodes();
point_list point_normals = c.get_point_normals();
point_list nodes = c->get_geod_nodes();
point_list point_normals = c->get_point_normals();
SG_LOG(SG_GENERAL, SG_ALERT, "number of geod nodes = " << nodes.size() );
SG_LOG(SG_GENERAL, SG_ALERT, "number of normals = " << point_normals.size() );
@ -509,9 +505,8 @@ void TGMatch::split_tile( TGConstruct& c ) {
// write the new shared edge points, normals, and segments for this
// tile
void TGMatch::write_shared( TGConstruct& c ) {
string base = c.get_work_base();
SGBucket b = c.get_bucket();
void TGMatch::write_shared( SGBucket b, TGConstruct* c ) {
string base = c->get_work_base();
string dir = base + "/Shared/" + b.gen_base_path();
string file = dir + "/" + b.gen_index_str();
@ -548,30 +543,30 @@ void TGMatch::write_shared( TGConstruct& c ) {
* means that the adjacent tile already has been built.
*/
if ( ! sw_flag ) {
fprintf( fp, "sw_node %.6f %.6f %.6f\n",
fprintf( fp, "sw_node %.10f %.10f %.10f\n",
sw_node.x(), sw_node.y(), sw_node.z() );
fprintf( fp, "sw_normal %.6f %.6f %.6f\n",
fprintf( fp, "sw_normal %.10f %.10f %.10f\n",
sw_normal.x(), sw_normal.y(), sw_normal.z() );
}
if ( ! se_flag ) {
fprintf( fp, "se_node %.6f %.6f %.6f\n",
fprintf( fp, "se_node %.10f %.10f %.10f\n",
se_node.x(), se_node.y(), se_node.z() );
fprintf( fp, "se_normal %.6f %.6f %.6f\n",
fprintf( fp, "se_normal %.10f %.10f %.10f\n",
se_normal.x(), se_normal.y(), se_normal.z() );
}
if ( ! nw_flag ) {
fprintf( fp, "nw_node %.6f %.6f %.6f\n",
fprintf( fp, "nw_node %.10f %.10f %.10f\n",
nw_node.x(), nw_node.y(), nw_node.z() );
fprintf( fp, "nw_normal %.6f %.6f %.6f\n",
fprintf( fp, "nw_normal %.10f %.10f %.10f\n",
nw_normal.x(), nw_normal.y(), nw_normal.z() );
}
if ( ! ne_flag ) {
fprintf( fp, "ne_node %.6f %.6f %.6f\n",
fprintf( fp, "ne_node %.10f %.10f %.10f\n",
ne_node.x(), ne_node.y(), ne_node.z() );
fprintf( fp, "ne_normal %.6f %.6f %.6f\n",
fprintf( fp, "ne_normal %.10f %.10f %.10f\n",
ne_normal.x(), ne_normal.y(), ne_normal.z() );
}
@ -580,10 +575,10 @@ void TGMatch::write_shared( TGConstruct& c ) {
fprintf( fp, "n_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)north_nodes.size(); ++i ) {
fprintf( fp, "n_node %.6f %.6f %.6f\n",
fprintf( fp, "n_node %.10f %.10f %.10f\n",
north_nodes[i].x(), north_nodes[i].y(),
north_nodes[i].z() );
fprintf( fp, "n_normal %.6f %.6f %.6f\n",
fprintf( fp, "n_normal %.10f %.10f %.10f\n",
north_normals[i].x(), north_normals[i].y(),
north_normals[i].z() );
}
@ -595,10 +590,10 @@ void TGMatch::write_shared( TGConstruct& c ) {
fprintf( fp, "s_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)south_nodes.size(); ++i ) {
fprintf( fp, "s_node %.6f %.6f %.6f\n",
fprintf( fp, "s_node %.10f %.10f %.10f\n",
south_nodes[i].x(), south_nodes[i].y(),
south_nodes[i].z() );
fprintf( fp, "s_normal %.6f %.6f %.6f\n",
fprintf( fp, "s_normal %.10f %.10f %.10f\n",
south_normals[i].x(), south_normals[i].y(),
south_normals[i].z() );
}
@ -610,10 +605,10 @@ void TGMatch::write_shared( TGConstruct& c ) {
fprintf( fp, "e_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)east_nodes.size(); ++i ) {
fprintf( fp, "e_node %.6f %.6f %.6f\n",
fprintf( fp, "e_node %.10f %.10f %.10f\n",
east_nodes[i].x(), east_nodes[i].y(),
east_nodes[i].z() );
fprintf( fp, "e_normal %.6f %.6f %.6f\n",
fprintf( fp, "e_normal %.10f %.10f %.10f\n",
east_normals[i].x(), east_normals[i].y(),
east_normals[i].z() );
}
@ -625,10 +620,10 @@ void TGMatch::write_shared( TGConstruct& c ) {
fprintf( fp, "w_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)west_nodes.size(); ++i ) {
fprintf( fp, "w_node %.6f %.6f %.6f\n",
fprintf( fp, "w_node %.10f %.10f %.10f\n",
west_nodes[i].x(), west_nodes[i].y(),
west_nodes[i].z() );
fprintf( fp, "w_normal %.6f %.6f %.6f\n",
fprintf( fp, "w_normal %.10f %.10f %.10f\n",
west_normals[i].x(), west_normals[i].y(),
west_normals[i].z() );
}
@ -642,28 +637,28 @@ void TGMatch::write_shared( TGConstruct& c ) {
for ( int i = 0; i < (int)north_segs.size(); ++i ) {
p1 = nodes[ north_segs[i].get_n1() ];
p2 = nodes[ north_segs[i].get_n2() ];
fprintf( fp, "n_seg %.6f %.6f %.6f %.6f\n",
fprintf( fp, "n_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
for ( int i = 0; i < (int)south_segs.size(); ++i ) {
p1 = nodes[ south_segs[i].get_n1() ];
p2 = nodes[ south_segs[i].get_n2() ];
fprintf( fp, "s_seg %.6f %.6f %.6f %.6f\n",
fprintf( fp, "s_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
for ( int i = 0; i < (int)east_segs.size(); ++i ) {
p1 = nodes[ east_segs[i].get_n1() ];
p2 = nodes[ east_segs[i].get_n2() ];
fprintf( fp, "e_seg %.6f %.6f %.6f %.6f\n",
fprintf( fp, "e_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
for ( int i = 0; i < (int)west_segs.size(); ++i ) {
p1 = nodes[ west_segs[i].get_n1() ];
p2 = nodes[ west_segs[i].get_n2() ];
fprintf( fp, "w_seg %.6f %.6f %.6f %.6f\n",
fprintf( fp, "w_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
#endif
@ -688,9 +683,9 @@ void insert_normal( point_list& normals, Point3D n, int i ) {
}
// Just add nodes and normals to the node list
void TGMatch::add_shared_nodes( TGConstruct& c ) {
void TGMatch::add_shared_nodes( TGConstruct* c ) {
TGNodes* nodes;
nodes = c.get_nodes();
nodes = c->get_nodes();
cout << " BEFORE ADDING SHARED NODES: " << nodes->size() << endl;
@ -739,7 +734,7 @@ void TGMatch::add_shared_nodes( TGConstruct& c ) {
// reassemble the tile pieces (combining the shared data and our own
// data)
void TGMatch::assemble_tile( TGConstruct& c ) {
void TGMatch::assemble_tile( TGConstruct* c ) {
int i;
TGTriNodes new_nodes;
new_nodes.clear();
@ -824,7 +819,7 @@ void TGMatch::assemble_tile( TGConstruct& c ) {
// add the body segments
point_list geod_nodes = c.get_geod_nodes();
point_list geod_nodes = c->get_geod_nodes();
TGTriSeg seg;
Point3D p1, p2;

View file

@ -83,35 +83,35 @@ public:
// load any previously existing shared data from all neighbors (if
// shared data for a component exists set that components flag to
// true
void load_neighbor_shared( TGConstruct& c );
void load_neighbor_shared( SGBucket b, std::string base );
// try to load any missing shared data from our own shared data file
void load_missing_shared( TGConstruct& c );
void load_missing_shared( SGBucket b, std::string base );
// scan the specified share file for the specified information
void scan_share_file( const std::string& dir, const SGBucket& b,
neighbor_type search, neighbor_type dest );
// try to find info for the specified shared component
void load_shared( const TGConstruct& c, neighbor_type n );
void load_shared( SGBucket b, std::string base, neighbor_type n );
// NEW TILE MATCHING - PRE TRIANGULATION
// Just add nodes and normals to the node list
void add_shared_nodes( TGConstruct& c );
void add_shared_nodes( TGConstruct* c );
// split up the tile between the shared edge points, normals, and
// segments and the body. This must be done after calling
// load_neighbor_data() and will ignore any shared data from the
// current tile that already exists from a neighbor.
void split_tile( TGConstruct& c );
void split_tile( SGBucket b, TGConstruct* c );
// write the new shared edge points, normals, and segments for
// this tile
void write_shared( TGConstruct& c );
void write_shared( SGBucket b, TGConstruct* c );
// reassemble the tile pieces (combining the shared data and our
// own data)
void assemble_tile( TGConstruct& c );
void assemble_tile( TGConstruct* c );
};

View file

@ -1,6 +0,0 @@
add_library(Triangulate STATIC
triangle.cxx triangle.hxx
trieles.cxx trieles.hxx
)

View file

@ -1,567 +0,0 @@
// triangle.cxx -- "Triangle" interface class
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: triangle.cxx,v 1.25 2005-10-31 18:45:19 curt Exp $
#include <simgear/compiler.h>
#include <Geometry/poly_support.hxx>
#include <Polygon/polygon.hxx>
#include <Polygon/superpoly.hxx>
#include <TriangleJRS/tri_support.h>
#include "triangle.hxx"
#include <stdlib.h>
using std::cout;
using std::endl;
using std::string;
// Constructor
TGTriangle::TGTriangle( void ) {
}
// Destructor
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 )
{
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 );
}
// next process the polygons
TGSuperPoly sp;
TGPolygon gpc_poly;
const_superpoly_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.superpolys[i].size() << endl;
debug_counter = 0;
current = gpc_polys.superpolys[i].begin();
last = gpc_polys.superpolys[i].end();
for ( ; current != last; ++current ) {
sp = *current;
gpc_poly = sp.get_poly();
// 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
// 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;
/*
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 << "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] );
}
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
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 ( 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;
}
// populate this class based on the specified gpc_polys list
int TGTriangle::rebuild( TGConstruct& c ) {
in_nodes.clear();
in_segs.clear();
#if 0
in_nodes = c.get_tri_nodes();
in_segs = c.get_tri_segs();
#endif
return 0;
}
// Front end triangulator for polygon list. Allocates and builds up
// all the needed structures for the triangulator, runs it, copies the
// results, and frees all the data structures used by the
// triangulator. "pass" can be 1 or 2. 1 = first pass which
// generates extra nodes for a better triangulation. 2 = second pass
// after split/reassem where we don't want any extra nodes generated.
int TGTriangle::run_triangulate( double angle, const int pass ) {
TGPolygon poly;
Point3D p;
struct triangulateio in, out, vorout;
int counter;
int i, j;
// point list
point_list node_list = in_nodes.get_node_list();
cout << "TRIANGULATE : NUMBER OF INPUT NODES: " << node_list.size() << endl;
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.numberofpointattributes = 1;
in.pointattributelist = (REAL *) malloc(in.numberofpoints *
in.numberofpointattributes *
sizeof(REAL));
for ( i = 0; i < in.numberofpoints * in.numberofpointattributes; ++i) {
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;
}
// 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();
}
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();
}
// hole list (make holes for airport ignore areas)
poly_list_iterator h_current, h_last;
in.numberofholes = 0;
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));
counter = 0;
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 ) {
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 ) {
if ( ! is_hole_area( 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;
}
}
}
}
}
in.regionlist = (REAL *) malloc(in.numberofregions * 4 * sizeof(REAL));
counter = 0;
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
if ( ! is_hole_area( 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)
}
}
}
}
}
// 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:
out.pointattributelist = (REAL *) NULL;
out.pointmarkerlist = (int *) NULL; // Not needed if -N or -B switch used.
out.trianglelist = (int *) NULL; // Not needed if -E switch used.
// Not needed if -E switch used or number of triangle attributes is zero:
out.triangleattributelist = (REAL *) NULL;
out.neighborlist = (int *) NULL; // Needed only if -n switch used.
// Needed only if segments are output (-p or -c) and -P not used:
out.segmentlist = (int *) NULL;
// Needed only if segments are output (-p or -c) and -P and -B not used:
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;
vorout.edgelist = (int *) NULL; // Needed only if -v switch used.
vorout.normlist = (REAL *) NULL; // Needed only if -v switch used.
// 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 0
if ( angle < 0.00001 ) {
tri_options = "pczAen";
} else {
char angle_str[256];
sprintf( angle_str, "%.2f", angle );
tri_options = "pczq";
tri_options += angle_str;
tri_options += "Aen";
}
#else
// TEST TEST TEST : NO ADDING POINTS
tri_options = "pzenYYQ";
#endif
// // 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";
} else {
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
cout << "TRIANGULATE : NUMBER OF OUTPUT NODES: " << out.numberofpoints << endl;
// 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 );
}
// 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] ) );
}
// 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 ) );
}
// free mem allocated to the "Triangle" structures
free(in.pointlist);
free(in.pointattributelist);
free(in.pointmarkerlist);
free(in.regionlist);
free(out.pointlist);
free(out.pointattributelist);
free(out.pointmarkerlist);
free(out.trianglelist);
free(out.triangleattributelist);
// free(out.trianglearealist);
free(out.neighborlist);
free(out.segmentlist);
free(out.segmentmarkerlist);
free(out.edgelist);
free(out.edgemarkerlist);
free(vorout.pointlist);
free(vorout.pointattributelist);
free(vorout.edgelist);
free(vorout.normlist);
return 0;
}

View file

@ -1,105 +0,0 @@
// triangle.hxx -- "Triangle" interface class
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: triangle.hxx,v 1.7 2004-11-19 22:25:50 curt Exp $
#ifndef _TRIANGLE_HXX
#define _TRIANGLE_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h>
#include <Geometry/point3d.hxx>
#include <Array/array.hxx>
#include <Main/construct.hxx>
#include <Geometry/trinodes.hxx>
#include <Geometry/trisegs.hxx>
#include <Clipper/priorities.hxx>
#include <Polygon/polygon.hxx>
#define REAL double
extern "C" {
#include <TriangleJRS/triangle.h>
}
#include "trieles.hxx"
class TGTriangle {
private:
// list of nodes
TGTriNodes in_nodes;
TGTriNodes out_nodes;
// list of segments
TGTriSegments in_segs;
TGTriSegments out_segs;
// polygon list
poly_list polylist[TG_MAX_AREA_TYPES];
// triangle list
triele_list elelist;
public:
// Constructor and destructor
TGTriangle( void );
~TGTriangle( void );
// add nodes from the dem fit
int add_nodes();
// populate this class based on the specified gpc_polys list
int build( const point_list& corner_list,
const point_list& fit_list,
const TGPolyList& gpc_polys );
// populate this class based on the specified gpc_polys list
int rebuild( TGConstruct& c );
// Front end triangulator for polygon list. Allocates and builds
// up all the needed structures for the triangulator, runs it,
// copies the results, and frees all the data structures used by
// the triangulator. "pass" can be 1 or 2. 1 = first pass which
// generates extra nodes for a better triangulation. 2 = second
// pass after split/reassem where we don't want any extra nodes
// generated.
int run_triangulate( double angle, const int pass );
inline TGTriNodes get_out_nodes() const { return out_nodes; }
inline size_t get_out_nodes_size() const { return out_nodes.size(); }
inline triele_list get_elelist() const { return elelist; }
inline TGTriSegments get_out_segs() const { return out_segs; }
};
#endif // _TRIANGLE_HXX

View file

@ -1,26 +0,0 @@
// trieles.cxx -- "Triangle" element management class
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id: trieles.cxx,v 1.2 2004-11-19 22:25:50 curt Exp $
#include "trieles.hxx"

View file

@ -136,7 +136,9 @@ void add_intermediate_tgnodes( int contour, const Point3D& start,
add_intermediate_tgnodes( contour, start, new_pt, nodes, result );
result->add_node( contour, new_pt );
SG_LOG(SG_GENERAL, SG_INFO, " added = " << new_pt);
SG_LOG(SG_GENERAL, SG_DEBUG, " added = " << new_pt);
// DEBUG : Was new node shared?
add_intermediate_tgnodes( contour, new_pt, end, nodes, result );
}

View file

@ -35,8 +35,6 @@
#include <Polygon/polygon.hxx>
#include <Polygon/chop.hxx>
#include <Triangulate/trieles.hxx>
#include <algorithm>
#include <iterator>

View file

@ -35,8 +35,8 @@
#include <simgear/math/sg_types.hxx>
#include <Polygon/polygon.hxx>
#include <Triangulate/trieles.hxx>
#include "trieles.hxx"
#include "trinodes.hxx"

View file

@ -33,7 +33,7 @@ int TGNodes::unique_add( const Point3D& p ) {
last = tg_node_list.end();
for ( ; current != last; ++current ) {
if ( close_enough_3d(p, (*current).GetPosition() ) ) {
if ( close_enough_2d(p, (*current).GetPosition() ) ) {
// cout << "found an existing match!" << endl;
return counter;
}
@ -59,7 +59,7 @@ int TGNodes::unique_add_fixed_elevation( const Point3D& p ) {
last = tg_node_list.end();
for ( ; current != last; ++current ) {
if ( close_enough_3d(p, (*current).GetPosition() ) ) {
if ( close_enough_2d(p, (*current).GetPosition() ) ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Adding fixed elev node : node already exists at " << counter << " old position is " << (*current).GetPosition() << " new position is " << p );
// Force the match to our position, and mark as fixed
@ -168,6 +168,7 @@ point_list TGNodes::get_normals( void ) const {
return points;
}
#if 0
bool TGNodes::LookupFixedElevation( Point3D p, double* z )
{
int index = find( p );
@ -183,3 +184,4 @@ bool TGNodes::LookupFixedElevation( Point3D p, double* z )
return found;
}
#endif

View file

@ -108,7 +108,7 @@ public:
// tolerance as unique_add(). Returns -1 if not found.
int find( const Point3D& p ) const;
bool LookupFixedElevation( Point3D p, double* z );
// bool LookupFixedElevation( Point3D p, double* z );
void SetElevation( int idx, double z ) { tg_node_list[idx].SetElevation( z ); }
// return the master node list

View file

@ -36,7 +36,7 @@
#include <simgear/math/sg_types.hxx>
#include <Triangulate/trieles.hxx>
#include <Geometry/trieles.hxx>
typedef std::vector < int_list > opt_list;
typedef opt_list::iterator opt_list_iterator;

View file

@ -37,7 +37,7 @@
#include <simgear/math/sg_types.hxx>
#include <Triangulate/trieles.hxx>
#include <Geometry/trieles.hxx>
typedef std::vector < int_list > opt_list;
typedef opt_list::iterator opt_list_iterator;

View file

@ -45,4 +45,5 @@ void TGSuperPoly::erase()
normals.erase();
texcoords.erase();
tris.erase();
face_normals.clear();
}

View file

@ -42,12 +42,13 @@ class TGSuperPoly {
private:
std::string material; // material/texture name
TGPolygon poly; // master polygon
TGPolygon normals; // corresponding normals
TGPolygon texcoords; // corresponding texture coordinates
TGPolygon tris; // triangulation
std::string flag; // For various potential record keeping needs
std::string material; // material/texture name
TGPolygon poly; // master polygon
TGPolygon normals; // corresponding normals
TGPolygon texcoords; // corresponding texture coordinates
TGPolygon tris; // triangulation
point_list face_normals; // triangle normals
std::string flag; // For various potential record keeping needs
public: