diff --git a/src/Prep/TerraFit/terrafit.cc b/src/Prep/TerraFit/terrafit.cc index bfd62368..9c087649 100644 --- a/src/Prep/TerraFit/terrafit.cc +++ b/src/Prep/TerraFit/terrafit.cc @@ -24,31 +24,31 @@ */ #include -#include -#include #include +#include #include +#include #ifndef _MSC_VER -# include -# ifdef __APPLE__ -# include -# else -# include -# endif +#include +#ifdef __APPLE__ +#include #else -# define S_ISDIR(a) ((a)&_S_IFDIR) -# include -# include -# define sleep(x) Sleep(x*1000) +#include +#endif +#else +#define S_ISDIR(a) ((a)&_S_IFDIR) +#include +#include +#define sleep(x) Sleep(x * 1000) #endif #include -#include #include -#include +#include #include +#include #include #include #include @@ -59,13 +59,12 @@ #include #include -using std::istream; using simgear::Dir; using simgear::PathList; +using std::istream; SGLockedQueue global_workQueue; - /* * Benchmark: Processing 800 individual buckets: * terrafit.cc: 52s 48s 48s @@ -73,38 +72,44 @@ SGLockedQueue global_workQueue; * * terrafit.cc takes on 20% of the time that terrafit.py took! */ -class ArrayMap: public Terra::Map { +class ArrayMap : public Terra::Map { public: - explicit ArrayMap(TGArray& array): array(array) { - width=array.get_cols(); - height=array.get_rows(); - min=30000; - max=-30000; - for (int i=0;imax) - max=v; - } - } - depth=32; + explicit ArrayMap(TGArray& array) + : array(array) + { + width = array.get_cols(); + height = array.get_rows(); + min = 30000; + max = -30000; + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + Terra::real v = eval(i, j); + if (v < min) + min = v; + if (v > max) + max = v; + } } + depth = 32; + } - virtual ~ArrayMap() {} - - virtual Terra::real eval(int i, int j) override { - return (Terra::real)array.get_array_elev(i,j); - } + virtual ~ArrayMap() {} + + virtual Terra::real eval(int i, int j) override + { + return (Terra::real)array.get_array_elev(i, j); + } + + /* No direct reading of .arr.gz files */ + virtual void rawRead(istream&) + { + } + virtual void textRead(istream&) + { + } - /* No direct reading of .arr.gz files */ - virtual void rawRead(istream&) { - } - virtual void textRead(istream&) { - } protected: - TGArray& array; + TGArray& array; }; static Terra::ImportMask default_mask; @@ -113,61 +118,57 @@ namespace Terra { * don't need one... */ static Terra::ImportMask default_mask; -Terra::ImportMask *MASK=&default_mask; +Terra::ImportMask* MASK = &default_mask; }; // namespace Terra -Terra::real error_threshold=40.0; -unsigned int min_points=50; -unsigned int point_limit=1000; -bool force=false; +Terra::real error_threshold = 40.0; +unsigned int min_points = 50; +unsigned int point_limit = 1000; +bool force = false; unsigned int num_threads = 1; inline int goal_not_met(Terra::GreedySubdivision* mesh) { - return - ( mesh->maxError() > error_threshold && - mesh->pointCount() < point_limit ) || - mesh->pointCount() < min_points; - + return (mesh->maxError() > error_threshold && mesh->pointCount() < point_limit) || mesh->pointCount() < min_points; } static void announce_goal(Terra::GreedySubdivision* mesh) { SG_LOG(SG_GENERAL, SG_INFO, "Goal conditions met:"); - SG_LOG(SG_GENERAL, SG_INFO, " error=" << mesh->maxError() << " [thresh="<< error_threshold << "]"); + SG_LOG(SG_GENERAL, SG_INFO, " error=" << mesh->maxError() << " [thresh=" << error_threshold << "]"); SG_LOG(SG_GENERAL, SG_INFO, " points=" << mesh->pointCount() << " [limit=" << point_limit << "]"); } void greedy_insertion(Terra::GreedySubdivision* mesh) { - - while( goal_not_met(mesh) ) - { - if( !mesh->greedyInsert() ) + while (goal_not_met(mesh)) { + if (!mesh->greedyInsert()) break; } announce_goal(mesh); } -bool endswith(const std::string& s1, const std::string& suffix) { - size_t s1len=s1.size(); - size_t sufflen=suffix.size(); +bool endswith(const std::string& s1, const std::string& suffix) +{ + size_t s1len = s1.size(); + size_t sufflen = suffix.size(); - if (s1len"); - SG_LOG(SG_GENERAL,SG_INFO, "\t -h | --help"); - SG_LOG(SG_GENERAL,SG_INFO, "\t -m | --minnodes 50"); - SG_LOG(SG_GENERAL,SG_INFO, "\t -x | --maxnodes 1000"); - SG_LOG(SG_GENERAL,SG_INFO, "\t -e | --maxerror 40"); - SG_LOG(SG_GENERAL,SG_INFO, "\t -f | --force"); - SG_LOG(SG_GENERAL,SG_INFO, "\t -j | --threads "); - SG_LOG(SG_GENERAL,SG_INFO, "\t -v | --version"); - SG_LOG(SG_GENERAL,SG_INFO, ""); - SG_LOG(SG_GENERAL,SG_INFO, "Algorithm will produce at least fitted nodes, but no"); - SG_LOG(SG_GENERAL,SG_INFO, "more than . Within that range, the algorithm will stop"); - SG_LOG(SG_GENERAL,SG_INFO, "if the maximum elevation error for any remaining point"); - SG_LOG(SG_GENERAL,SG_INFO, "drops below meters."); - SG_LOG(SG_GENERAL,SG_INFO, ""); - SG_LOG(SG_GENERAL,SG_INFO, "Increasing the maxnodes value and/or decreasing maxerror"); - SG_LOG(SG_GENERAL,SG_INFO, "will produce a better surface approximation."); - SG_LOG(SG_GENERAL,SG_INFO, ""); - SG_LOG(SG_GENERAL,SG_INFO, "The input file must be a .arr.gz file such as that produced"); - SG_LOG(SG_GENERAL,SG_INFO, "by the hgtchop utility."); - SG_LOG(SG_GENERAL,SG_INFO, ""); - SG_LOG(SG_GENERAL,SG_INFO, "Force will overwrite existing .arr.gz files, even if the input is older"); - SG_LOG(SG_GENERAL,SG_INFO, ""); - SG_LOG(SG_GENERAL,SG_INFO, "**** NOTE ****:"); - SG_LOG(SG_GENERAL,SG_INFO, "If a directory is input all .arr.gz files in directory will be"); - SG_LOG(SG_GENERAL,SG_INFO, "processed recursively."); - SG_LOG(SG_GENERAL,SG_INFO, ""); - SG_LOG(SG_GENERAL,SG_INFO, "The output file(s) is/are called .fit.gz and is simply a list of"); - SG_LOG(SG_GENERAL,SG_INFO, "from the resulting fitted surface nodes. The user of the"); - SG_LOG(SG_GENERAL,SG_INFO, ".fit.gz file will need to retriangulate the surface."); + SG_LOG(SG_GENERAL, SG_INFO, "Usage: " << progname << " [options] "); + SG_LOG(SG_GENERAL, SG_INFO, "\t -h | --help"); + SG_LOG(SG_GENERAL, SG_INFO, "\t -m | --minnodes 50"); + SG_LOG(SG_GENERAL, SG_INFO, "\t -x | --maxnodes 1000"); + SG_LOG(SG_GENERAL, SG_INFO, "\t -e | --maxerror 40"); + SG_LOG(SG_GENERAL, SG_INFO, "\t -f | --force"); + SG_LOG(SG_GENERAL, SG_INFO, "\t -j | --threads "); + SG_LOG(SG_GENERAL, SG_INFO, "\t -v | --version"); + SG_LOG(SG_GENERAL, SG_INFO, ""); + SG_LOG(SG_GENERAL, SG_INFO, "Algorithm will produce at least fitted nodes, but no"); + SG_LOG(SG_GENERAL, SG_INFO, "more than . Within that range, the algorithm will stop"); + SG_LOG(SG_GENERAL, SG_INFO, "if the maximum elevation error for any remaining point"); + SG_LOG(SG_GENERAL, SG_INFO, "drops below meters."); + SG_LOG(SG_GENERAL, SG_INFO, ""); + SG_LOG(SG_GENERAL, SG_INFO, "Increasing the maxnodes value and/or decreasing maxerror"); + SG_LOG(SG_GENERAL, SG_INFO, "will produce a better surface approximation."); + SG_LOG(SG_GENERAL, SG_INFO, ""); + SG_LOG(SG_GENERAL, SG_INFO, "The input file must be a .arr.gz file such as that produced"); + SG_LOG(SG_GENERAL, SG_INFO, "by the hgtchop utility."); + SG_LOG(SG_GENERAL, SG_INFO, ""); + SG_LOG(SG_GENERAL, SG_INFO, "Force will overwrite existing .arr.gz files, even if the input is older"); + SG_LOG(SG_GENERAL, SG_INFO, ""); + SG_LOG(SG_GENERAL, SG_INFO, "**** NOTE ****:"); + SG_LOG(SG_GENERAL, SG_INFO, "If a directory is input all .arr.gz files in directory will be"); + SG_LOG(SG_GENERAL, SG_INFO, "processed recursively."); + SG_LOG(SG_GENERAL, SG_INFO, ""); + SG_LOG(SG_GENERAL, SG_INFO, "The output file(s) is/are called .fit.gz and is simply a list of"); + SG_LOG(SG_GENERAL, SG_INFO, "from the resulting fitted surface nodes. The user of the"); + SG_LOG(SG_GENERAL, SG_INFO, ".fit.gz file will need to retriangulate the surface."); } -struct option options[]={ - {"help",no_argument,NULL,'h'}, - {"minnodes",required_argument,NULL,'m'}, - {"maxnodes",required_argument,NULL,'x'}, - {"maxerror",required_argument,NULL,'e'}, - {"force",no_argument,NULL,'f'}, - {"version",no_argument,NULL,'v'}, - {"threads",required_argument,NULL,'j'}, - {NULL,0,NULL,0} +struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "minnodes", required_argument, NULL, 'm' }, + { "maxnodes", required_argument, NULL, 'x' }, + { "maxerror", required_argument, NULL, 'e' }, + { "force", no_argument, NULL, 'f' }, + { "version", no_argument, NULL, 'v' }, + { "threads", required_argument, NULL, 'j' }, + { NULL, 0, NULL, 0 } }; -int main(int argc, char** argv) { - sglog().setLogLevels( SG_ALL, SG_INFO ); +int main(int argc, char** argv) +{ + sglog().setLogLevels(SG_ALL, SG_INFO); int option; auto start_time = std::chrono::high_resolution_clock::now(); - while ((option=getopt_long(argc,argv,"hm:x:e:fvj:",options,NULL))!=-1) { + while ((option = getopt_long(argc, argv, "hm:x:e:fvj:", options, NULL)) != -1) { switch (option) { - case 'h': - usage(argv[0],""); - break; - case 'm': - min_points=atoi(optarg); - break; - case 'x': - point_limit=atoi(optarg); - break; - case 'e': - error_threshold=atof(optarg); - break; - case 'f': - force=true; - break; - case 'v': - SG_LOG(SG_GENERAL,SG_INFO,argv[0] << " version " << getTGVersion()); - exit(0); - break; - case 'j': - num_threads = atoi(optarg); - break; - case '?': - usage(argv[0],std::string("Unknown option:")+(char)optopt); - exit(1); + case 'h': + usage(argv[0], ""); + break; + case 'm': + min_points = atoi(optarg); + break; + case 'x': + point_limit = atoi(optarg); + break; + case 'e': + error_threshold = atof(optarg); + break; + case 'f': + force = true; + break; + case 'v': + SG_LOG(SG_GENERAL, SG_INFO, argv[0] << " version " << getTGVersion()); + exit(0); + break; + case 'j': + num_threads = atoi(optarg); + break; + case '?': + usage(argv[0], std::string("Unknown option:") + (char)optopt); + exit(1); } } @@ -341,8 +342,8 @@ int main(int argc, char** argv) { SG_LOG(SG_GENERAL, SG_INFO, "Max points = " << point_limit); SG_LOG(SG_GENERAL, SG_INFO, "Max error = " << error_threshold); - if (optind > threads; - for (unsigned int t=0; t> threads; + for (unsigned int t = 0; t < num_threads; ++t) { std::shared_ptr thread(new FitThread); thread->start(); threads.push_back(thread); @@ -362,7 +363,7 @@ int main(int argc, char** argv) { sleep(1); } - for (unsigned int t=0; tjoin(); } @@ -370,7 +371,9 @@ int main(int argc, char** argv) { auto finish_time = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = finish_time - start_time; - std::cout << std::endl << "Elapsed time: " << elapsed.count() << " seconds" << std::endl << std::endl; + std::cout << std::endl + << "Elapsed time: " << elapsed.count() << " seconds" << std::endl + << std::endl; return EXIT_SUCCESS; }