add bounding box calculations to optimize tesselation
This commit is contained in:
parent
feeaf602b7
commit
cf6d6f42b9
11 changed files with 477 additions and 37 deletions
|
@ -145,6 +145,7 @@ void TGConstruct::add_poly( int area, const TGPolygon &poly, string material ) {
|
||||||
|
|
||||||
bool TGConstruct::load_poly(const string& path) {
|
bool TGConstruct::load_poly(const string& path) {
|
||||||
bool poly3d = false;
|
bool poly3d = false;
|
||||||
|
bool with_tp = false;
|
||||||
string first_line;
|
string first_line;
|
||||||
string poly_name;
|
string poly_name;
|
||||||
AreaType poly_type;
|
AreaType poly_type;
|
||||||
|
@ -160,40 +161,104 @@ bool TGConstruct::load_poly(const string& path) {
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TGPolygon poly;
|
TGPolygon poly;
|
||||||
|
TGTexParams tp;
|
||||||
Point3D p;
|
Point3D p;
|
||||||
|
|
||||||
// (this could break things, why is it here) in >> skipcomment;
|
// (this could break things, why is it here) in >> skipcomment;
|
||||||
while ( !in.eof() ) {
|
while ( !in.eof() ) {
|
||||||
in >> first_line;
|
in >> first_line;
|
||||||
if ( first_line == "#2D" ) {
|
if ( first_line == "#2D" ) {
|
||||||
poly3d = false;
|
poly3d = false;
|
||||||
|
with_tp = false;
|
||||||
|
|
||||||
in >> poly_name;
|
in >> poly_name;
|
||||||
num_polys = 1;
|
num_polys = 1;
|
||||||
} else if ( first_line == "#2D_WITH_MASK" ) {
|
} else if ( first_line == "#2D_WITH_MASK" ) {
|
||||||
poly3d = false;
|
poly3d = false;
|
||||||
|
with_tp = false;
|
||||||
|
|
||||||
|
in >> poly_name;
|
||||||
|
in >> num_polys;
|
||||||
|
} else if ( first_line == "#2D_WITH_TPS" ) {
|
||||||
|
poly3d = false;
|
||||||
|
with_tp = true;
|
||||||
|
|
||||||
in >> poly_name;
|
in >> poly_name;
|
||||||
in >> num_polys;
|
in >> num_polys;
|
||||||
} else if ( first_line == "#3D" ) {
|
} else if ( first_line == "#3D" ) {
|
||||||
poly3d = true;
|
poly3d = true;
|
||||||
|
with_tp = false;
|
||||||
|
|
||||||
in >> poly_name;
|
in >> poly_name;
|
||||||
num_polys = 1;
|
num_polys = 1;
|
||||||
} else {
|
} else {
|
||||||
// support old format (default to 2d)
|
// support old format (default to 2d)
|
||||||
poly3d = false;
|
poly3d = false;
|
||||||
|
with_tp = false;
|
||||||
|
|
||||||
poly_name = first_line;
|
poly_name = first_line;
|
||||||
num_polys = 1;
|
num_polys = 1;
|
||||||
}
|
}
|
||||||
poly_type = get_area_type( poly_name );
|
poly_type = get_area_type( poly_name );
|
||||||
|
|
||||||
int area = (int)poly_type;
|
int area = (int)poly_type;
|
||||||
string material = get_area_name( area );
|
string material;
|
||||||
|
|
||||||
|
// only allow 1000 shapes per material
|
||||||
|
int extension = polys_in.area_size( area ) / 1000;
|
||||||
|
|
||||||
|
SG_LOG( SG_CLIPPER, SG_INFO, "extension " << extension );
|
||||||
|
|
||||||
|
if (extension)
|
||||||
|
{
|
||||||
|
char buff[32];
|
||||||
|
sprintf( buff, "%s_%d", get_area_name( area ).c_str(), extension );
|
||||||
|
|
||||||
|
SG_LOG( SG_CLIPPER, SG_INFO, "buff " << buff );
|
||||||
|
|
||||||
|
material = buff;
|
||||||
|
|
||||||
|
SG_LOG( SG_CLIPPER, SG_INFO, "material " << material );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material = get_area_name( area );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generate a new Shape for the poly
|
// Generate a new Shape for the poly
|
||||||
TGShape shape;
|
TGShape shape;
|
||||||
TGSuperPoly sp;
|
TGSuperPoly sp;
|
||||||
|
|
||||||
for (k=0; k<num_polys;k++) {
|
for (k=0; k<num_polys;k++) {
|
||||||
|
|
||||||
|
if ( with_tp ) {
|
||||||
|
double width, length;
|
||||||
|
double heading;
|
||||||
|
double minu, maxu;
|
||||||
|
double minv, maxv;
|
||||||
|
|
||||||
|
in >> x;
|
||||||
|
in >> y;
|
||||||
|
in >> width;
|
||||||
|
in >> length;
|
||||||
|
in >> heading;
|
||||||
|
in >> minu;
|
||||||
|
in >> maxu;
|
||||||
|
in >> minv;
|
||||||
|
in >> maxv;
|
||||||
|
|
||||||
|
tp.set_ref( Point3D(x, y, 0.0f) );
|
||||||
|
tp.set_width( width );
|
||||||
|
tp.set_length( length );
|
||||||
|
tp.set_heading( heading );
|
||||||
|
tp.set_minu( minu );
|
||||||
|
tp.set_maxu( maxu );
|
||||||
|
tp.set_minv( minv );
|
||||||
|
tp.set_maxv( maxv );
|
||||||
|
}
|
||||||
|
|
||||||
in >> contours;
|
in >> contours;
|
||||||
|
|
||||||
SG_LOG( SG_CLIPPER, SG_INFO, "Loading " << path << ":" << poly_name << "-" << poly_type << " contours = " << contours );
|
SG_LOG( SG_CLIPPER, SG_INFO, "Loading " << path << ":" << poly_name << "-" << poly_type << " contours = " << contours );
|
||||||
|
@ -271,9 +336,19 @@ bool TGConstruct::load_poly(const string& path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
poly = remove_dups( poly );
|
poly = remove_dups( poly );
|
||||||
sp.set_poly( poly );
|
|
||||||
|
sp.set_poly( poly );
|
||||||
sp.set_material( material );
|
sp.set_material( material );
|
||||||
|
|
||||||
shape.sps.push_back( sp );
|
shape.sps.push_back( sp );
|
||||||
|
if ( with_tp ) {
|
||||||
|
shape.textured = true;
|
||||||
|
shape.tps.push_back( tp );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shape.textured = false;
|
||||||
|
}
|
||||||
|
|
||||||
in >> skipcomment;
|
in >> skipcomment;
|
||||||
}
|
}
|
||||||
|
@ -1222,6 +1297,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
|
|
||||||
// copy all of the superpolys and texparams
|
// copy all of the superpolys and texparams
|
||||||
shape.SetMask( clipped );
|
shape.SetMask( clipped );
|
||||||
|
shape.textured = polys_in.get_textured( i, j );
|
||||||
shape.sps = polys_in.get_shape( i, j ).sps;
|
shape.sps = polys_in.get_shape( i, j ).sps;
|
||||||
shape.tps = polys_in.get_shape( i, j ).tps;
|
shape.tps = polys_in.get_shape( i, j ).tps;
|
||||||
|
|
||||||
|
@ -1275,6 +1351,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
|
|
||||||
sp.set_material( material );
|
sp.set_material( material );
|
||||||
sp.set_poly( remains );
|
sp.set_poly( remains );
|
||||||
|
shape.SetMask( remains );
|
||||||
shape.sps.push_back( sp );
|
shape.sps.push_back( sp );
|
||||||
|
|
||||||
polys_clipped.add_shape( (int)get_sliver_target_area_type(), shape );
|
polys_clipped.add_shape( (int)get_sliver_target_area_type(), shape );
|
||||||
|
@ -1543,13 +1620,16 @@ void TGConstruct::SaveSharedEdgeData( void )
|
||||||
void TGConstruct::TesselatePolys( void )
|
void TGConstruct::TesselatePolys( void )
|
||||||
{
|
{
|
||||||
// tesselate the polygons and prepair them for final output
|
// tesselate the polygons and prepair them for final output
|
||||||
point_list extra = nodes.get_geod_nodes();
|
point_list poly_extra;
|
||||||
|
Point3D min, max;
|
||||||
|
|
||||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||||
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||||
|
poly.get_bounding_box(min, max);
|
||||||
|
poly_extra = nodes.get_geod_inside( min, max );
|
||||||
|
|
||||||
SG_LOG( SG_CLIPPER, SG_INFO, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
SG_LOG( SG_CLIPPER, SG_INFO, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
||||||
shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) <<
|
shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) <<
|
||||||
": flag = " << polys_clipped.get_flag(area, shape, segment));
|
": flag = " << polys_clipped.get_flag(area, shape, segment));
|
||||||
|
@ -1569,7 +1649,7 @@ void TGConstruct::TesselatePolys( void )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TGPolygon tri = polygon_tesselate_alt_with_extra( poly, extra, false );
|
TGPolygon tri = polygon_tesselate_alt_with_extra( poly, poly_extra, false );
|
||||||
|
|
||||||
// ensure all added nodes are accounted for
|
// ensure all added nodes are accounted for
|
||||||
for (int k=0; k< tri.contours(); k++) {
|
for (int k=0; k< tri.contours(); k++) {
|
||||||
|
@ -1763,18 +1843,16 @@ void TGConstruct::CalcTextureCoordinates( void )
|
||||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||||
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||||
SG_LOG( SG_CLIPPER, SG_INFO, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
SG_LOG( SG_CLIPPER, SG_INFO, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
||||||
shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) <<
|
shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
|
||||||
": flag = " << polys_clipped.get_flag(area, shape, segment));
|
|
||||||
|
|
||||||
TGPolygon tri = polys_clipped.get_tris( area, shape, segment );
|
TGPolygon tri = polys_clipped.get_tris( area, shape, segment );
|
||||||
TGPolygon tc;
|
TGPolygon tc;
|
||||||
|
|
||||||
if ( polys_clipped.get_flag( area, shape, segment ) == "textured" ) {
|
if ( polys_clipped.get_textured( area, shape ) ) {
|
||||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "USE TEXTURE PARAMS for tex coord calculations" );
|
SG_LOG(SG_GENERAL, SG_INFO, "USE TEXTURE PARAMS for tex coord calculations" );
|
||||||
// tc = linear_tex_coords( tri, clipped_polys.texparams[i][j] );
|
tc = linear_tex_coords( tri, polys_clipped.get_texparams(area, shape, segment) );
|
||||||
tc = area_tex_coords( tri );
|
|
||||||
} else {
|
} else {
|
||||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "USE SIMGEAR for tex coord calculations" );
|
SG_LOG(SG_GENERAL, SG_INFO, "USE SIMGEAR for tex coord calculations" );
|
||||||
tc = area_tex_coords( tri );
|
tc = area_tex_coords( tri );
|
||||||
}
|
}
|
||||||
polys_clipped.set_texcoords( area, shape, segment, tc );
|
polys_clipped.set_texcoords( area, shape, segment, tc );
|
||||||
|
|
|
@ -54,6 +54,7 @@ class TGShape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TGPolygon clip_mask;
|
TGPolygon clip_mask;
|
||||||
|
bool textured;
|
||||||
superpoly_list sps;
|
superpoly_list sps;
|
||||||
texparams_list tps;
|
texparams_list tps;
|
||||||
|
|
||||||
|
@ -130,6 +131,15 @@ public:
|
||||||
shapes[area][shape].clip_mask = mask;
|
shapes[area][shape].clip_mask = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool get_textured( unsigned int area, unsigned int shape )
|
||||||
|
{
|
||||||
|
return shapes[area][shape].textured;
|
||||||
|
}
|
||||||
|
inline void set_textured( unsigned int area, unsigned int shape, bool t )
|
||||||
|
{
|
||||||
|
shapes[area][shape].textured = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline TGSuperPoly& get_superpoly( unsigned int area, unsigned int shape, unsigned int segment )
|
inline TGSuperPoly& get_superpoly( unsigned int area, unsigned int shape, unsigned int segment )
|
||||||
{
|
{
|
||||||
|
@ -177,6 +187,10 @@ public:
|
||||||
{
|
{
|
||||||
return shapes[area][shape].sps[segment].get_material();
|
return shapes[area][shape].sps[segment].get_material();
|
||||||
}
|
}
|
||||||
|
inline TGTexParams& get_texparams( unsigned int area, unsigned int shape, unsigned int segment )
|
||||||
|
{
|
||||||
|
return shapes[area][shape].tps[segment];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline TGPolygon get_texcoords( unsigned int area, unsigned int shape, unsigned int segment )
|
inline TGPolygon get_texcoords( unsigned int area, unsigned int shape, unsigned int segment )
|
||||||
|
|
|
@ -93,6 +93,9 @@ public:
|
||||||
Point3D& operator *= ( const double d ); // multiplication by a constant
|
Point3D& operator *= ( const double d ); // multiplication by a constant
|
||||||
Point3D& operator /= ( const double d ); // division by a constant
|
Point3D& operator /= ( const double d ); // division by a constant
|
||||||
|
|
||||||
|
bool operator > ( const Point3D& p );
|
||||||
|
bool operator < ( const Point3D& p );
|
||||||
|
|
||||||
void setx(const double x);
|
void setx(const double x);
|
||||||
void sety(const double y);
|
void sety(const double y);
|
||||||
void setz(const double z);
|
void setz(const double z);
|
||||||
|
@ -138,6 +141,8 @@ public:
|
||||||
bool IsEqual2D(const Point3D& a) const; // equality check in X,Y only
|
bool IsEqual2D(const Point3D& a) const; // equality check in X,Y only
|
||||||
bool HasElevation() const; // does point have elevation data?
|
bool HasElevation() const; // does point have elevation data?
|
||||||
|
|
||||||
|
bool IsWithin( Point3D min, Point3D max ) const;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
double round(double d)
|
double round(double d)
|
||||||
{
|
{
|
||||||
|
@ -316,6 +321,16 @@ inline Point3D& Point3D::operator /= ( const double d )
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Point3D::operator < ( const Point3D& p )
|
||||||
|
{
|
||||||
|
return ( (n[PX] < p.n[PX]) && (n[PY] < p.n[PY]) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Point3D::operator > ( const Point3D& p )
|
||||||
|
{
|
||||||
|
return ( (n[PX] > p.n[PX]) && (n[PY] > p.n[PY]) );
|
||||||
|
}
|
||||||
|
|
||||||
inline void Point3D::setx(const double x) {
|
inline void Point3D::setx(const double x) {
|
||||||
n[PX] = x;
|
n[PX] = x;
|
||||||
}
|
}
|
||||||
|
@ -424,6 +439,11 @@ inline bool Point3D::HasElevation() const
|
||||||
return ( fabs( n[PZ] + 9999.0 ) > fgPoint3_Epsilon );
|
return ( fabs( n[PZ] + 9999.0 ) > fgPoint3_Epsilon );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Point3D::IsWithin( Point3D min, Point3D max ) const
|
||||||
|
{
|
||||||
|
return ( (min.n[PX] < n[PX]) && (min.n[PY] < n[PY]) &&
|
||||||
|
(max.n[PX] > n[PX]) && (max.n[PY] > n[PY]) );
|
||||||
|
}
|
||||||
|
|
||||||
// FRIENDS
|
// FRIENDS
|
||||||
|
|
||||||
|
|
|
@ -1541,7 +1541,6 @@ void* tgShapefileOpenLayer( void* ds_id, const char* layer_name ) {
|
||||||
|
|
||||||
void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* description )
|
void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* description )
|
||||||
{
|
{
|
||||||
OGRDataSource* datasource = (OGRDataSource *)ds_id;
|
|
||||||
OGRLayer* layer = (OGRLayer*)l_id;
|
OGRLayer* layer = (OGRLayer*)l_id;
|
||||||
OGRPolygon* polygon = new OGRPolygon();
|
OGRPolygon* polygon = new OGRPolygon();
|
||||||
|
|
||||||
|
@ -1553,21 +1552,21 @@ void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, c
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Polygon with less than 3 points");
|
SG_LOG(SG_GENERAL, SG_DEBUG, "Polygon with less than 3 points");
|
||||||
skip_ring=true;
|
skip_ring=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Current we ignore the hole-flag and instead assume
|
// FIXME: Current we ignore the hole-flag and instead assume
|
||||||
// that the first ring is not a hole and the rest
|
// that the first ring is not a hole and the rest
|
||||||
// are holes
|
// are holes
|
||||||
OGRLinearRing *ring=new OGRLinearRing();
|
OGRLinearRing *ring=new OGRLinearRing();
|
||||||
for (unsigned int pt = 0; pt < contour.size(); pt++) {
|
for (unsigned int pt = 0; pt < contour.size(); pt++) {
|
||||||
OGRPoint *point=new OGRPoint();
|
OGRPoint *point=new OGRPoint();
|
||||||
|
|
||||||
point->setX( contour[pt].x() );
|
point->setX( contour[pt].x() );
|
||||||
point->setY( contour[pt].y() );
|
point->setY( contour[pt].y() );
|
||||||
point->setZ( 0.0 );
|
point->setZ( 0.0 );
|
||||||
ring->addPoint(point);
|
ring->addPoint(point);
|
||||||
}
|
}
|
||||||
ring->closeRings();
|
ring->closeRings();
|
||||||
|
|
||||||
if (!skip_ring) {
|
if (!skip_ring) {
|
||||||
polygon->addRingDirectly(ring);
|
polygon->addRingDirectly(ring);
|
||||||
}
|
}
|
||||||
|
@ -1586,8 +1585,6 @@ void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, c
|
||||||
|
|
||||||
void tgShapefileCloseLayer( void* l_id )
|
void tgShapefileCloseLayer( void* l_id )
|
||||||
{
|
{
|
||||||
OGRLayer* layer = (OGRLayer *)l_id;
|
|
||||||
|
|
||||||
//OGRLayer::DestroyLayer( layer );
|
//OGRLayer::DestroyLayer( layer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,25 @@ point_list TGNodes::get_geod_nodes( void ) const {
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
point_list TGNodes::get_geod_inside( Point3D min, Point3D max ) const {
|
||||||
|
point_list points;
|
||||||
|
const_node_list_iterator current, last;
|
||||||
|
|
||||||
|
// see if point already exists
|
||||||
|
current = tg_node_list.begin();
|
||||||
|
last = tg_node_list.end();
|
||||||
|
|
||||||
|
for ( ; current != last; ++current ) {
|
||||||
|
Point3D pt = (*current).GetPosition();
|
||||||
|
|
||||||
|
if ( pt.IsWithin( min, max ) ) {
|
||||||
|
points.push_back( pt );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector< SGVec3d > TGNodes::get_wgs84_nodes_as_SGVec3d( void ) const {
|
std::vector< SGVec3d > TGNodes::get_wgs84_nodes_as_SGVec3d( void ) const {
|
||||||
const_node_list_iterator current, last;
|
const_node_list_iterator current, last;
|
||||||
std::vector< SGVec3d > points;
|
std::vector< SGVec3d > points;
|
||||||
|
|
|
@ -150,6 +150,9 @@ public:
|
||||||
// return a point list of geodetic nodes
|
// return a point list of geodetic nodes
|
||||||
point_list get_geod_nodes() const;
|
point_list get_geod_nodes() const;
|
||||||
|
|
||||||
|
// Find all the nodes within a bounding box
|
||||||
|
point_list get_geod_inside( Point3D min, Point3D max ) const;
|
||||||
|
|
||||||
// return a point list of wgs84 nodes
|
// return a point list of wgs84 nodes
|
||||||
std::vector< SGVec3d > get_wgs84_nodes_as_SGVec3d() const;
|
std::vector< SGVec3d > get_wgs84_nodes_as_SGVec3d() const;
|
||||||
point_list get_wgs84_nodes_as_Point3d() const;
|
point_list get_wgs84_nodes_as_Point3d() const;
|
||||||
|
|
|
@ -279,6 +279,144 @@ static void clip_and_write_polys_with_mask( string root, long int p_index,
|
||||||
fclose( rfp );
|
fclose( rfp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clip_and_write_polys_with_tps( string root, long int p_index,
|
||||||
|
const string &poly_type,
|
||||||
|
SGBucket b,
|
||||||
|
const poly_list& segments,
|
||||||
|
const texparams_list& tps,
|
||||||
|
bool preserve3d )
|
||||||
|
{
|
||||||
|
Point3D c, min, max, p;
|
||||||
|
|
||||||
|
c = Point3D( b.get_center_lon(), b.get_center_lat(), 0 );
|
||||||
|
double span = b.get_width();
|
||||||
|
TGPolygon base, result;
|
||||||
|
char tile_name[256], poly_index[256];
|
||||||
|
|
||||||
|
// calculate bucket dimensions
|
||||||
|
if ( (c.y() >= -89.0) && (c.y() < 89.0) ) {
|
||||||
|
min.setx( c.x() - span / 2.0 );
|
||||||
|
max.setx( c.x() + span / 2.0 );
|
||||||
|
min.sety( c.y() - SG_HALF_BUCKET_SPAN );
|
||||||
|
max.sety( c.y() + SG_HALF_BUCKET_SPAN );
|
||||||
|
} else if ( c.y() < -89.0) {
|
||||||
|
min.setx( -90.0 );
|
||||||
|
max.setx( -89.0 );
|
||||||
|
min.sety( -180.0 );
|
||||||
|
max.sety( 180.0 );
|
||||||
|
} else if ( c.y() >= 89.0) {
|
||||||
|
min.setx( 89.0 );
|
||||||
|
max.setx( 90.0 );
|
||||||
|
min.sety( -180.0 );
|
||||||
|
max.sety( 180.0 );
|
||||||
|
} else {
|
||||||
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||||
|
"Out of range latitude in clip_and_write_poly() = " << c.y() );
|
||||||
|
}
|
||||||
|
|
||||||
|
min.setz( 0.0 );
|
||||||
|
max.setz( 0.0 );
|
||||||
|
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, " (" << min << ") (" << max << ")" );
|
||||||
|
|
||||||
|
// set up clipping tile
|
||||||
|
base.add_node( 0, Point3D(min.x(), min.y(), 0) );
|
||||||
|
base.add_node( 0, Point3D(max.x(), min.y(), 0) );
|
||||||
|
base.add_node( 0, Point3D(max.x(), max.y(), 0) );
|
||||||
|
base.add_node( 0, Point3D(min.x(), max.y(), 0) );
|
||||||
|
|
||||||
|
// SG_LOG( SG_GENERAL, SG_DEBUG, "base = 4 vertices" );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FILE *bfp= fopen("base", "w");
|
||||||
|
* gpc_write_polygon(bfp, &base);
|
||||||
|
* fclose(bfp);
|
||||||
|
*/
|
||||||
|
|
||||||
|
poly_list clipped_shapes;
|
||||||
|
texparams_list clipped_tps;
|
||||||
|
TGPolygon shape;
|
||||||
|
TGTexParams tp;
|
||||||
|
unsigned int s;
|
||||||
|
|
||||||
|
for ( s = 0; s < segments.size(); s++ ) {
|
||||||
|
shape = segments[s];
|
||||||
|
|
||||||
|
// SG_LOG(SG_GENERAL, SG_DEBUG, "shape contours = " << shape.contours() );
|
||||||
|
// for ( int ii = 0; ii < shape.contours(); ii++ )
|
||||||
|
// SG_LOG(SG_GENERAL, SG_DEBUG, " hole = " << shape.get_hole_flag(ii) );
|
||||||
|
|
||||||
|
result = tgPolygonInt( base, shape );
|
||||||
|
|
||||||
|
// write_polygon(shape, "shape");
|
||||||
|
// write_polygon(result, "result");
|
||||||
|
|
||||||
|
// SG_LOG(SG_GENERAL, SG_DEBUG, "result contours = " << result.contours() );
|
||||||
|
// for ( int ii = 0; ii < result.contours(); ii++ ) {
|
||||||
|
// SG_LOG(SG_GENERAL, SG_DEBUG, " hole = " << result.get_hole_flag(ii) );
|
||||||
|
// }
|
||||||
|
|
||||||
|
if ( preserve3d )
|
||||||
|
result.inherit_elevations( shape );
|
||||||
|
|
||||||
|
if ( result.contours() > 0 ) {
|
||||||
|
clipped_shapes.push_back( result );
|
||||||
|
clipped_tps.push_back( tps[s] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we can write the file
|
||||||
|
long int t_index = b.gen_index();
|
||||||
|
string path = root + "/" + b.gen_base_path();
|
||||||
|
|
||||||
|
SGPath sgp( path );
|
||||||
|
sgp.append( "dummy" );
|
||||||
|
sgp.create_dir( 0755 );
|
||||||
|
|
||||||
|
sprintf( tile_name, "%ld", t_index );
|
||||||
|
string polyfile = path + "/" + tile_name;
|
||||||
|
|
||||||
|
sprintf( poly_index, "%ld", p_index );
|
||||||
|
polyfile += ".";
|
||||||
|
polyfile += poly_index;
|
||||||
|
|
||||||
|
FILE *rfp = fopen( polyfile.c_str(), "w" );
|
||||||
|
|
||||||
|
if ( preserve3d )
|
||||||
|
fprintf( rfp, "#3D_WITH_TPS\n" );
|
||||||
|
else
|
||||||
|
fprintf( rfp, "#2D_WITH_TPS\n" );
|
||||||
|
fprintf( rfp, "%s\n", poly_type.c_str() );
|
||||||
|
|
||||||
|
fprintf( rfp, "%d\n", (int)clipped_shapes.size() );
|
||||||
|
|
||||||
|
for (s=0; s<clipped_shapes.size(); s++) {
|
||||||
|
shape = clipped_shapes[s];
|
||||||
|
tp = clipped_tps[s];
|
||||||
|
|
||||||
|
fprintf( rfp, "%.15f %.15f %.15f %.15f %.15f %.15f %.15f %.15f %.15f\n",
|
||||||
|
tp.get_ref().x(), tp.get_ref().y(), tp.get_width(), tp.get_length(),
|
||||||
|
tp.get_heading(),
|
||||||
|
tp.get_minu(), tp.get_maxu(), tp.get_minu(), tp.get_maxu());
|
||||||
|
|
||||||
|
fprintf( rfp, "%d\n", shape.contours() );
|
||||||
|
for ( int i = 0; i < shape.contours(); ++i ) {
|
||||||
|
fprintf( rfp, "%d\n", shape.contour_size(i) );
|
||||||
|
fprintf( rfp, "%d\n", shape.get_hole_flag(i) );
|
||||||
|
for ( int j = 0; j < shape.contour_size(i); ++j ) {
|
||||||
|
p = shape.get_pt( i, j );
|
||||||
|
if ( preserve3d )
|
||||||
|
fprintf( rfp, "%.15f %.15f %.15f\n", p.x(), p.y(), p.z() );
|
||||||
|
else
|
||||||
|
fprintf( rfp, "%.15f %.15f\n", p.x(), p.y() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf( rfp, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose( rfp );
|
||||||
|
}
|
||||||
|
|
||||||
static void clip_and_write_poly_tp( string root, long int p_index,
|
static void clip_and_write_poly_tp( string root, long int p_index,
|
||||||
const string &poly_type,
|
const string &poly_type,
|
||||||
SGBucket b, const TGPolygon& shape,
|
SGBucket b, const TGPolygon& shape,
|
||||||
|
@ -834,6 +972,165 @@ void tgChopNormalPolygonTP( const string& path, const string& poly_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tgChopNormalPolygonsWithTP(const std::string& path, const std::string& poly_type,
|
||||||
|
const poly_list& segments, const texparams_list& tps, bool preserve3d )
|
||||||
|
{
|
||||||
|
Point3D min, max, p;
|
||||||
|
TGPolygon shape;
|
||||||
|
long int index;
|
||||||
|
int i, j;
|
||||||
|
unsigned int s;
|
||||||
|
|
||||||
|
// bail out immediately if poly_list is empty
|
||||||
|
if ( segments.size() == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get next polygon index
|
||||||
|
index = poly_index_next();
|
||||||
|
|
||||||
|
min = Point3D( 200.0 );
|
||||||
|
max = Point3D( -200.0 );
|
||||||
|
|
||||||
|
for ( s = 0; s < segments.size(); s++) {
|
||||||
|
shape = segments[s];
|
||||||
|
|
||||||
|
// find min/max of polygon
|
||||||
|
for ( i = 0; i < shape.contours(); i++ ) {
|
||||||
|
for ( j = 0; j < shape.contour_size(i); j++ ) {
|
||||||
|
p = shape.get_pt( i, j );
|
||||||
|
|
||||||
|
if ( p.x() < min.x() ) min.setx( p.x() ); if ( p.y() < min.y() ) min.sety( p.y() ); if ( p.x() > max.x() ) max.setx( p.x() ); if ( p.y() > max.y() ) max.sety( p.y() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, " min = " << min << " max = " << max );
|
||||||
|
|
||||||
|
// find buckets for min, and max points of convex hull.
|
||||||
|
// note to self: self, you should think about checking for
|
||||||
|
// polygons that span the date line
|
||||||
|
SGBucket b_min( min.x(), min.y() );
|
||||||
|
SGBucket b_max( max.x(), max.y() );
|
||||||
|
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, " Bucket min = " << b_min );
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, " Bucket max = " << b_max );
|
||||||
|
|
||||||
|
if ( b_min == b_max ) {
|
||||||
|
// shape entirely contained in a single bucket, write and bail
|
||||||
|
clip_and_write_polys_with_tps( path, index, poly_type, b_min, segments, tps, preserve3d );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGBucket b_cur;
|
||||||
|
int dx, dy;
|
||||||
|
|
||||||
|
sgBucketDiff(b_min, b_max, &dx, &dy);
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, " polygon spans tile boundaries" );
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, " dx = " << dx << " dy = " << dy );
|
||||||
|
|
||||||
|
if ( (dx > 2880) || (dy > 1440) )
|
||||||
|
throw sg_exception("something is really wrong in split_polygon()!!!!");
|
||||||
|
|
||||||
|
if ( dy <= 1 ) {
|
||||||
|
// we are down to at most two rows, write each column and then bail
|
||||||
|
double min_center_lat = b_min.get_center_lat();
|
||||||
|
double min_center_lon = b_min.get_center_lon();
|
||||||
|
for ( j = 0; j <= dy; ++j ) {
|
||||||
|
for ( i = 0; i <= dx; ++i ) {
|
||||||
|
b_cur = sgBucketOffset(min_center_lon, min_center_lat, i, j);
|
||||||
|
clip_and_write_polys_with_tps( path, index, poly_type, b_cur, segments, tps, preserve3d );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have two or more rows left, split in half (along a
|
||||||
|
// horizontal dividing line) and recurse with each half
|
||||||
|
// find mid point (integer math)
|
||||||
|
int mid = (dy + 1) / 2 - 1;
|
||||||
|
|
||||||
|
// determine horizontal clip line
|
||||||
|
SGBucket b_clip = sgBucketOffset(min.x(), min.y(), 0, mid);
|
||||||
|
double clip_line = b_clip.get_center_lat();
|
||||||
|
if ( (clip_line >= -90.0 + SG_HALF_BUCKET_SPAN) &&
|
||||||
|
(clip_line < 90.0 - SG_HALF_BUCKET_SPAN) )
|
||||||
|
clip_line += SG_HALF_BUCKET_SPAN;
|
||||||
|
else if ( clip_line < -89.0 )
|
||||||
|
clip_line = -89.0;
|
||||||
|
else if ( clip_line >= 89.0 )
|
||||||
|
clip_line = 90.0;
|
||||||
|
else {
|
||||||
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||||
|
"Out of range latitude in clip_and_write_poly() = " << clip_line );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Crop bottom area (hopefully by putting this in it's own
|
||||||
|
// scope we can shorten the life of some really large data
|
||||||
|
// structures to reduce memory use)
|
||||||
|
//
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG,
|
||||||
|
"Generating bottom half (" << min.y() << "-" << clip_line << ")" );
|
||||||
|
|
||||||
|
TGPolygon bottom, bottom_clip;
|
||||||
|
poly_list bottom_clip_list;
|
||||||
|
texparams_list bottom_tp_list;
|
||||||
|
|
||||||
|
bottom.erase();
|
||||||
|
bottom.add_node( 0, Point3D(-180.0, min.y(), 0) );
|
||||||
|
bottom.add_node( 0, Point3D(180.0, min.y(), 0) );
|
||||||
|
bottom.add_node( 0, Point3D(180.0, clip_line, 0) );
|
||||||
|
bottom.add_node( 0, Point3D(-180.0, clip_line, 0) );
|
||||||
|
|
||||||
|
for (s=0; s<segments.size(); s++) {
|
||||||
|
bottom_clip.erase();
|
||||||
|
bottom_clip = tgPolygonInt( bottom, segments[s] );
|
||||||
|
|
||||||
|
if ( bottom_clip.contours() > 0 ) {
|
||||||
|
bottom_clip_list.push_back( bottom_clip );
|
||||||
|
bottom_tp_list.push_back( tps[s] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tgChopNormalPolygonsWithTP( path, poly_type, bottom_clip_list, bottom_tp_list, preserve3d );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Crop top area (hopefully by putting this in it's own scope
|
||||||
|
// we can shorten the life of some really large data
|
||||||
|
// structures to reduce memory use)
|
||||||
|
//
|
||||||
|
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG,
|
||||||
|
"Generating top half (" << clip_line << "-" <<
|
||||||
|
max.y() << ")" );
|
||||||
|
|
||||||
|
TGPolygon top, top_clip;
|
||||||
|
poly_list top_clip_list;
|
||||||
|
texparams_list top_tp_list;
|
||||||
|
|
||||||
|
top.erase();
|
||||||
|
top.add_node( 0, Point3D(-180.0, clip_line, 0) );
|
||||||
|
top.add_node( 0, Point3D(180.0, clip_line, 0) );
|
||||||
|
top.add_node( 0, Point3D(180.0, max.y(), 0) );
|
||||||
|
top.add_node( 0, Point3D(-180.0, max.y(), 0) );
|
||||||
|
|
||||||
|
for (s=0; s<segments.size(); s++) {
|
||||||
|
top_clip.erase();
|
||||||
|
top_clip = tgPolygonInt( top, segments[s] );
|
||||||
|
|
||||||
|
if ( top_clip.contours() > 0 ) {
|
||||||
|
top_clip_list.push_back( top_clip );
|
||||||
|
top_tp_list.push_back( tps[s] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tgChopNormalPolygonsWithTP( path, poly_type, top_clip_list, top_tp_list, preserve3d );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// process polygon shape (chop up along tile boundaries and write each
|
// process polygon shape (chop up along tile boundaries and write each
|
||||||
// polygon piece to a file) This has a front end to a crude clipper
|
// polygon piece to a file) This has a front end to a crude clipper
|
||||||
// that doesn't handle holes so beware. This routine is appropriate
|
// that doesn't handle holes so beware. This routine is appropriate
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "polygon.hxx"
|
#include "polygon.hxx"
|
||||||
#include "texparams.hxx"
|
#include "texparams.hxx"
|
||||||
|
|
||||||
|
@ -38,12 +37,12 @@ void tgChopNormalPolygon( const std::string& path, const std::string& poly_type,
|
||||||
const TGPolygon& shape, bool preserve3d );
|
const TGPolygon& shape, bool preserve3d );
|
||||||
|
|
||||||
void tgChopNormalPolygonsWithMask(const std::string& path, const std::string& poly_type,
|
void tgChopNormalPolygonsWithMask(const std::string& path, const std::string& poly_type,
|
||||||
const poly_list& segments, bool preserve3d );
|
const poly_list& segments, bool preserve3d );
|
||||||
|
|
||||||
// process polygon shape (chop up along tile boundaries and write each
|
// process polygon shape (chop up along tile boundaries and write each
|
||||||
// polygon piece to a file)
|
// polygon piece to a file)
|
||||||
void tgChopNormalPolygonTP( const std::string& path, const std::string& poly_type,
|
void tgChopNormalPolygonsWithTP( const std::string& path, const std::string& poly_type,
|
||||||
const TGPolygon& shape, const TGTexParams& tp, bool preserve3d );
|
const poly_list& segments, const texparams_list& tps, bool preserve3d );
|
||||||
|
|
||||||
// process polygon shape (chop up along tile boundaries and write each
|
// process polygon shape (chop up along tile boundaries and write each
|
||||||
// polygon piece to a file) This has a front end to a crude clipper
|
// polygon piece to a file) This has a front end to a crude clipper
|
||||||
|
|
|
@ -2098,7 +2098,8 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
|
||||||
op->next = op;
|
op->next = op;
|
||||||
op->prev = op;
|
op->prev = op;
|
||||||
SetHoleState(e, outRec);
|
SetHoleState(e, outRec);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
OutRec *outRec = m_PolyOuts[e->outIdx];
|
OutRec *outRec = m_PolyOuts[e->outIdx];
|
||||||
OutPt* op = outRec->pts;
|
OutPt* op = outRec->pts;
|
||||||
|
@ -2109,12 +2110,17 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
|
||||||
{
|
{
|
||||||
//check for 'rounding' artefacts ...
|
//check for 'rounding' artefacts ...
|
||||||
if (outRec->sides == esNeither && pt.Y == op->pt.Y)
|
if (outRec->sides == esNeither && pt.Y == op->pt.Y)
|
||||||
|
{
|
||||||
if (ToFront)
|
if (ToFront)
|
||||||
{
|
{
|
||||||
if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt
|
if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt
|
||||||
}
|
}
|
||||||
else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt
|
else
|
||||||
|
{
|
||||||
|
if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
outRec->sides = (EdgeSide)(outRec->sides | e->side);
|
outRec->sides = (EdgeSide)(outRec->sides | e->side);
|
||||||
if (outRec->sides == esBoth)
|
if (outRec->sides == esBoth)
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,6 +153,20 @@ inline void set_pt( int contour, int i, const Point3D& p )
|
||||||
poly[contour][i] = p;
|
poly[contour][i] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void get_bounding_box( Point3D& min, Point3D& max )
|
||||||
|
{
|
||||||
|
min = Point3D( std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), 0.0 );
|
||||||
|
max = Point3D( -std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity(), 0.0 );
|
||||||
|
|
||||||
|
for ( int i = 0; i < contours(); i++ ) {
|
||||||
|
for (unsigned int j = 0; j < poly[i].size(); j++) {
|
||||||
|
Point3D pt = poly[i][j];
|
||||||
|
if ( pt < min ) { min = pt; }
|
||||||
|
if ( pt > max ) { max = pt; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get and set an arbitrary point inside the specified polygon contour
|
// get and set an arbitrary point inside the specified polygon contour
|
||||||
inline Point3D get_point_inside( const int contour ) const
|
inline Point3D get_point_inside( const int contour ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -185,9 +185,7 @@ void processLineStringWithTextureInfo(OGRLineString* poGeometry,
|
||||||
int width)
|
int width)
|
||||||
{
|
{
|
||||||
poly_list segments;
|
poly_list segments;
|
||||||
TGPolygon segment;
|
|
||||||
texparams_list tps;
|
texparams_list tps;
|
||||||
TGTexParams tp;
|
|
||||||
tg::Line line;
|
tg::Line line;
|
||||||
Point3D p0, p1;
|
Point3D p0, p1;
|
||||||
double heading, dist, az2;
|
double heading, dist, az2;
|
||||||
|
@ -246,12 +244,7 @@ void processLineStringWithTextureInfo(OGRLineString* poGeometry,
|
||||||
// make a plygons from the line segments
|
// make a plygons from the line segments
|
||||||
tg::makePolygonsTP(line,width,segments,tps);
|
tg::makePolygonsTP(line,width,segments,tps);
|
||||||
|
|
||||||
for ( i = 0; i < (int)segments.size(); ++i ) {
|
tgChopNormalPolygonsWithTP(work_dir, area_type, segments, tps, false);
|
||||||
segment = segments[i];
|
|
||||||
tp = tps[i];
|
|
||||||
|
|
||||||
tgChopNormalPolygonTP(work_dir, area_type, segment, tp, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void processPolygon(OGRPolygon* poGeometry,
|
void processPolygon(OGRPolygon* poGeometry,
|
||||||
|
|
Loading…
Add table
Reference in a new issue