1
0
Fork 0
terragear/src/Lib/Optimize/genfans.cxx

256 lines
6.9 KiB
C++
Raw Normal View History

2000-02-09 19:51:45 +00:00
// genfans.cxx -- Combine individual triangles into more optimal fans.
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
Contributed by Bruce Finney: The following files have been changed to enable the latest Terragear CVS to compile with MSVC++ 5.0 .\construct\clipper\clipper.cxx for( int i - lots of places .\construct\genoutput\genobj.cxx fix directory logic for windows, line 320 and following .\construct\main\main.cxx windows does not have an opendir function added code for windows directory functions disabled the mem allocation limit code - windows does not have similar functions for ( int i - several places .\construct\match\match.cxx moved the definition of file and command outside of the ifdef line 420 .\lib\e00\e00.cxx for( int i - several places .\lib\e00\e00.cxx use simgear/compiler.h constructs .\lib\geometry\contour_tree.hxx removed a cout statement .\lib\geometry\poly_support.cxx added float.h changed 1.0e+999 to DBL_MAX, windows doesn't go that big lots of for ( int i changes lines 193 and 208 no != operator defined - changed logic line 801 flag should be int, not bool, get_hole_flag returns int .\lib\landcover\landcover.cxx .\lib\landcover\landcover.hxx add include simgear/compiler.h see comments .\lib\optimize\genfans.cxx function canonify added return at end, windows complains added using std for cout and endl .\lib\optimize\genstrips.cxx function tgGenStrips no return value, moved by_node into outer scope fix for ( int i ... .\lib\poly2tri\construct.c added include <memory.h> for windows remove unused variables lines 435 & 437 .\lib\poly2tri\misc.c added HAVE_SYS_TIME_H logic for sys/time.h include file added logic to uses windows functions for time and rand .\lib\poly2tri\monotone.c added include <memory.h> for windows lines 286-288 remove unused variables .\lib\poly2tri\tri.c remove sys/time.h - no time functions called added include <memory.h> for windows .\lib\polygon\polygon.cxx function polygon_to_tristrip will not compile I don't think the logic is complete, no returned data added if else endif around function and polygon_to_tristrip_old, renamed _old function. Search of code reveals that function is not called by anyone. .\lib\polygon\superpoly.cxx changed include <superpoly.hxx> to "superpoly.hxx" .\lib\polygon\superpoly.hxx add include <windows.h> for windows before include <gl.h> needed for definitions used in Microsoft version of opengl .\lib\shapelib\dbfopen.c added include files for windows lines 195-197 271-272 515-517 removed unused variables .\lib\shapelib\shpopen.c added #include <stdlib.h> for malloc() and friends added include files for windows line 279 527 813 1127 removed unused variables line 827 cast result to int .\lib\win32\mkdir.cpp documented function, remove debug lines .\prep\demraw2ascii\main.c lines 46-50 remove unused variables .\prep\demraw2ascii\rawdem.c line 47 changed logic to compile with MSVC line 244-256 set real constants to float, windows complains with double constants .\prep\genairports\build.cxx lots of for ( int i changes .\prep\genairports\main.cxx fix mkdir logic for windows .\prep\genairports\output.cxx added using std cout endl lots of for ( int i changes fix mkdir logic for windows .\prep\genairports\runway.cxx for ( int i changes lines 117-118 161-162 remove default values for function parameters .\prep\gshhs\main.cxx added using std cout .\prep\shapefile\noaa_decode.cxx .\prep\shapefile\shape_decode.cxx added using std for cout lines 45-49 moved unused variables inside #if 0 block
2000-11-25 19:39:46 +00:00
#include <simgear/compiler.h>
#include STL_IOSTREAM
2000-02-09 19:51:45 +00:00
#include "genfans.hxx"
2001-03-23 21:59:33 +00:00
SG_USING_STD( cout );
SG_USING_STD( endl );
Contributed by Bruce Finney: The following files have been changed to enable the latest Terragear CVS to compile with MSVC++ 5.0 .\construct\clipper\clipper.cxx for( int i - lots of places .\construct\genoutput\genobj.cxx fix directory logic for windows, line 320 and following .\construct\main\main.cxx windows does not have an opendir function added code for windows directory functions disabled the mem allocation limit code - windows does not have similar functions for ( int i - several places .\construct\match\match.cxx moved the definition of file and command outside of the ifdef line 420 .\lib\e00\e00.cxx for( int i - several places .\lib\e00\e00.cxx use simgear/compiler.h constructs .\lib\geometry\contour_tree.hxx removed a cout statement .\lib\geometry\poly_support.cxx added float.h changed 1.0e+999 to DBL_MAX, windows doesn't go that big lots of for ( int i changes lines 193 and 208 no != operator defined - changed logic line 801 flag should be int, not bool, get_hole_flag returns int .\lib\landcover\landcover.cxx .\lib\landcover\landcover.hxx add include simgear/compiler.h see comments .\lib\optimize\genfans.cxx function canonify added return at end, windows complains added using std for cout and endl .\lib\optimize\genstrips.cxx function tgGenStrips no return value, moved by_node into outer scope fix for ( int i ... .\lib\poly2tri\construct.c added include <memory.h> for windows remove unused variables lines 435 & 437 .\lib\poly2tri\misc.c added HAVE_SYS_TIME_H logic for sys/time.h include file added logic to uses windows functions for time and rand .\lib\poly2tri\monotone.c added include <memory.h> for windows lines 286-288 remove unused variables .\lib\poly2tri\tri.c remove sys/time.h - no time functions called added include <memory.h> for windows .\lib\polygon\polygon.cxx function polygon_to_tristrip will not compile I don't think the logic is complete, no returned data added if else endif around function and polygon_to_tristrip_old, renamed _old function. Search of code reveals that function is not called by anyone. .\lib\polygon\superpoly.cxx changed include <superpoly.hxx> to "superpoly.hxx" .\lib\polygon\superpoly.hxx add include <windows.h> for windows before include <gl.h> needed for definitions used in Microsoft version of opengl .\lib\shapelib\dbfopen.c added include files for windows lines 195-197 271-272 515-517 removed unused variables .\lib\shapelib\shpopen.c added #include <stdlib.h> for malloc() and friends added include files for windows line 279 527 813 1127 removed unused variables line 827 cast result to int .\lib\win32\mkdir.cpp documented function, remove debug lines .\prep\demraw2ascii\main.c lines 46-50 remove unused variables .\prep\demraw2ascii\rawdem.c line 47 changed logic to compile with MSVC line 244-256 set real constants to float, windows complains with double constants .\prep\genairports\build.cxx lots of for ( int i changes .\prep\genairports\main.cxx fix mkdir logic for windows .\prep\genairports\output.cxx added using std cout endl lots of for ( int i changes fix mkdir logic for windows .\prep\genairports\runway.cxx for ( int i changes lines 117-118 161-162 remove default values for function parameters .\prep\gshhs\main.cxx added using std cout .\prep\shapefile\noaa_decode.cxx .\prep\shapefile\shape_decode.cxx added using std for cout lines 45-49 moved unused variables inside #if 0 block
2000-11-25 19:39:46 +00:00
2000-02-09 19:51:45 +00:00
// make sure the list is expanded at least to hold "n" and then push
// "i" onto the back of the "n" list.
2000-05-08 17:17:21 +00:00
static void add_and_expand( opt_list& by_node, int n, int i ) {
2000-02-09 19:51:45 +00:00
int_list empty;
int size = (int)by_node.size();
if ( size > n ) {
// ok
} else {
// cout << "capacity = " << by_node.capacity() << endl;
// cout << "size = " << size << " n = " << n
// << " need to push = " << n - size + 1 << endl;
for ( int i = 0; i < n - size + 1; ++i ) {
by_node.push_back(empty);
}
}
by_node[n].push_back(i);
}
// given an input triangle, shuffle nodes so that "center" is the
// first node, but maintain winding order.
static FGTriEle canonify( const FGTriEle& t, int center ) {
if ( t.get_n1() == center ) {
// already ok
return t;
} else if ( t.get_n2() == center ) {
return FGTriEle( t.get_n2(), t.get_n3(), t.get_n1(), 0.0 );
} else if ( t.get_n3() == center ) {
return FGTriEle( t.get_n3(), t.get_n1(), t.get_n2(), 0.0 );
} else {
cout << "ERROR, index doesn't refer to this triangle!!!" << endl;
exit(-1);
}
Contributed by Bruce Finney: The following files have been changed to enable the latest Terragear CVS to compile with MSVC++ 5.0 .\construct\clipper\clipper.cxx for( int i - lots of places .\construct\genoutput\genobj.cxx fix directory logic for windows, line 320 and following .\construct\main\main.cxx windows does not have an opendir function added code for windows directory functions disabled the mem allocation limit code - windows does not have similar functions for ( int i - several places .\construct\match\match.cxx moved the definition of file and command outside of the ifdef line 420 .\lib\e00\e00.cxx for( int i - several places .\lib\e00\e00.cxx use simgear/compiler.h constructs .\lib\geometry\contour_tree.hxx removed a cout statement .\lib\geometry\poly_support.cxx added float.h changed 1.0e+999 to DBL_MAX, windows doesn't go that big lots of for ( int i changes lines 193 and 208 no != operator defined - changed logic line 801 flag should be int, not bool, get_hole_flag returns int .\lib\landcover\landcover.cxx .\lib\landcover\landcover.hxx add include simgear/compiler.h see comments .\lib\optimize\genfans.cxx function canonify added return at end, windows complains added using std for cout and endl .\lib\optimize\genstrips.cxx function tgGenStrips no return value, moved by_node into outer scope fix for ( int i ... .\lib\poly2tri\construct.c added include <memory.h> for windows remove unused variables lines 435 & 437 .\lib\poly2tri\misc.c added HAVE_SYS_TIME_H logic for sys/time.h include file added logic to uses windows functions for time and rand .\lib\poly2tri\monotone.c added include <memory.h> for windows lines 286-288 remove unused variables .\lib\poly2tri\tri.c remove sys/time.h - no time functions called added include <memory.h> for windows .\lib\polygon\polygon.cxx function polygon_to_tristrip will not compile I don't think the logic is complete, no returned data added if else endif around function and polygon_to_tristrip_old, renamed _old function. Search of code reveals that function is not called by anyone. .\lib\polygon\superpoly.cxx changed include <superpoly.hxx> to "superpoly.hxx" .\lib\polygon\superpoly.hxx add include <windows.h> for windows before include <gl.h> needed for definitions used in Microsoft version of opengl .\lib\shapelib\dbfopen.c added include files for windows lines 195-197 271-272 515-517 removed unused variables .\lib\shapelib\shpopen.c added #include <stdlib.h> for malloc() and friends added include files for windows line 279 527 813 1127 removed unused variables line 827 cast result to int .\lib\win32\mkdir.cpp documented function, remove debug lines .\prep\demraw2ascii\main.c lines 46-50 remove unused variables .\prep\demraw2ascii\rawdem.c line 47 changed logic to compile with MSVC line 244-256 set real constants to float, windows complains with double constants .\prep\genairports\build.cxx lots of for ( int i changes .\prep\genairports\main.cxx fix mkdir logic for windows .\prep\genairports\output.cxx added using std cout endl lots of for ( int i changes fix mkdir logic for windows .\prep\genairports\runway.cxx for ( int i changes lines 117-118 161-162 remove default values for function parameters .\prep\gshhs\main.cxx added using std cout .\prep\shapefile\noaa_decode.cxx .\prep\shapefile\shape_decode.cxx added using std for cout lines 45-49 moved unused variables inside #if 0 block
2000-11-25 19:39:46 +00:00
// MSVC kludge (code should never reach this point, but it makes
// the MSVC compiler happy)
return t;
2000-02-09 19:51:45 +00:00
}
// returns a list of triangle indices
static int_list make_best_fan( const triele_list& master_tris,
const int center, const int_list& local_tris )
{
int_list best_result;
// try starting with each of local_tris to find the best fan
// arrangement
for ( int start = 0; start < (int)local_tris.size(); ++start ) {
// cout << "trying with first triangle = " << local_tris[start] << endl;
int_list tmp_result;
tmp_result.clear();
FGTriEle current_tri;
FGTriEle test;
current_tri = canonify( master_tris[local_tris[start]], center );
tmp_result.push_back( local_tris[start] );
// follow the ring
int next = -1;
bool matches = true;
while ( (next != start) && matches ) {
// find next triangle in ring
matches = false;
for ( int i = 0; i < (int)local_tris.size(); ++i ) {
test = canonify( master_tris[local_tris[i]], center );
if ( current_tri.get_n3() == test.get_n2() ) {
if ( i != start ) {
// cout << " next triangle = " << local_tris[i] << endl;
current_tri = test;
tmp_result.push_back( local_tris[i] );
matches = true;
next = i;
break;
}
}
}
}
if ( tmp_result.size() == local_tris.size() ) {
// we found a complete usage, no need to go on
// cout << "we found a complete usage, no need to go on" << endl;
best_result = tmp_result;
break;
} else if ( tmp_result.size() > best_result.size() ) {
// we found a better way to fan
// cout << "we found a better fan arrangement" << endl;
best_result = tmp_result;
}
}
return best_result;
}
static bool in_fan(int index, const int_list& fan ) {
const_int_list_iterator current = fan.begin();
const_int_list_iterator last = fan.end();
for ( ; current != last; ++current ) {
if ( index == *current ) {
return true;
}
}
return false;
}
// recursive build fans from triangle list
2000-05-08 17:17:21 +00:00
opt_list FGGenFans::greedy_build( triele_list tris ) {
2000-02-09 19:51:45 +00:00
cout << "starting greedy build of fans" << endl;
fans.clear();
while ( ! tris.empty() ) {
// traverse the triangle list and for each node, build a list of
// triangles that attach to it.
2000-05-08 17:17:21 +00:00
// cout << "building by_node list" << endl;
opt_list by_node;
by_node.clear();
2000-02-09 19:51:45 +00:00
for ( int i = 0; i < (int)tris.size(); ++i ) {
int n1 = tris[i].get_n1();
int n2 = tris[i].get_n2();
int n3 = tris[i].get_n3();
add_and_expand( by_node, n1, i );
add_and_expand( by_node, n2, i );
add_and_expand( by_node, n3, i );
}
// find the node in the tris list that attaches to the most
// triangles
// cout << "find most connected node" << endl;
int_list biggest_group;
2000-05-08 17:17:21 +00:00
opt_list_iterator r_current = by_node.begin();
opt_list_iterator r_last = by_node.end();
2000-02-09 19:51:45 +00:00
int index = 0;
int counter = 0;
for ( ; r_current != r_last; ++r_current ) {
if ( r_current->size() > biggest_group.size() ) {
biggest_group = *r_current;
index = counter;
}
++counter;
}
// cout << "triangle pool = " << tris.size() << endl;
// cout << "biggest_group = " << biggest_group.size() << endl;
// cout << "center node = " << index << endl;
// make the best fan we can out of this group
// cout << "before make_best_fan()" << endl;
int_list best_fan = make_best_fan( tris, index, biggest_group );
// cout << "after make_best_fan()" << endl;
// generate point form of best_fan
int_list node_list;
node_list.clear();
int_list_iterator i_start = best_fan.begin();
int_list_iterator i_current = i_start;
int_list_iterator i_last = best_fan.end();
for ( ; i_current != i_last; ++i_current ) {
FGTriEle t = canonify( tris[*i_current], index );
if ( i_start == i_current ) {
node_list.push_back( t.get_n1() );
node_list.push_back( t.get_n2() );
}
node_list.push_back( t.get_n3() );
}
// cout << "best list size = " << node_list.size() << endl;
// add this fan to the fan list
fans.push_back( node_list );
// delete the triangles in best_fan out of tris and repeat
triele_list_iterator t_current = tris.begin();
triele_list_iterator t_last = tris.end();
counter = 0;
while ( t_current != t_last ) {
if ( in_fan(counter, best_fan) ) {
// cout << "erasing "
// << t_current->get_n1() << ","
// << t_current->get_n2() << ","
// << t_current->get_n3()
// << " from master tri pool"
// << endl;
tris.erase( t_current );
} else {
++t_current;
}
++counter;
}
}
cout << "end of greedy build of fans" << endl;
cout << "average fan size = " << ave_size() << endl;
return fans;
}
// report average fan size
double FGGenFans::ave_size() {
double sum = 0.0;
2000-05-08 17:17:21 +00:00
opt_list_iterator current = fans.begin();
opt_list_iterator last = fans.end();
2000-02-09 19:51:45 +00:00
for ( ; current != last; ++current ) {
sum += current->size();
}
return sum / (double)fans.size();
}