1
0
Fork 0
terragear/src/Lib/Optimize/genfans.cxx
curt c8cc7e2a61 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

255 lines
6.9 KiB
C++

// 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$
#include <simgear/compiler.h>
#include STL_IOSTREAM
#include "genfans.hxx"
FG_USING_STD( cout );
FG_USING_STD( endl );
// make sure the list is expanded at least to hold "n" and then push
// "i" onto the back of the "n" list.
static void add_and_expand( opt_list& by_node, int n, int i ) {
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);
}
// MSVC kludge (code should never reach this point, but it makes
// the MSVC compiler happy)
return t;
}
// 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
opt_list FGGenFans::greedy_build( triele_list tris ) {
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.
// cout << "building by_node list" << endl;
opt_list by_node;
by_node.clear();
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;
opt_list_iterator r_current = by_node.begin();
opt_list_iterator r_last = by_node.end();
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;
opt_list_iterator current = fans.begin();
opt_list_iterator last = fans.end();
for ( ; current != last; ++current ) {
sum += current->size();
}
return sum / (double)fans.size();
}