1
0
Fork 0

[terrafit] source code format only

This commit is contained in:
Scott Giese 2019-04-22 20:24:27 -05:00
parent 53cb8086b3
commit 93440e4acd

View file

@ -24,31 +24,31 @@
*/ */
#include <chrono> #include <chrono>
#include <string>
#include <stdio.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string>
#ifndef _MSC_VER #ifndef _MSC_VER
# include <unistd.h> #include <unistd.h>
# ifdef __APPLE__ #ifdef __APPLE__
# include <Prep/Terra/getopt.h> #include <Prep/Terra/getopt.h>
# else
# include <getopt.h>
# endif
#else #else
# define S_ISDIR(a) ((a)&_S_IFDIR) #include <getopt.h>
# include <windows.h> #endif
# include <Prep/Terra/getopt.h> #else
# define sleep(x) Sleep(x*1000) #define S_ISDIR(a) ((a)&_S_IFDIR)
#include <Prep/Terra/getopt.h>
#include <windows.h>
#define sleep(x) Sleep(x * 1000)
#endif #endif
#include <zlib.h> #include <zlib.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/bucket/newbucket.hxx> #include <simgear/bucket/newbucket.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_dir.hxx> #include <simgear/misc/sg_dir.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/threads/SGQueue.hxx> #include <simgear/threads/SGQueue.hxx>
#include <simgear/threads/SGThread.hxx> #include <simgear/threads/SGThread.hxx>
@ -59,13 +59,12 @@
#include <Prep/Terra/Map.h> #include <Prep/Terra/Map.h>
#include <Prep/Terra/Mask.h> #include <Prep/Terra/Mask.h>
using std::istream;
using simgear::Dir; using simgear::Dir;
using simgear::PathList; using simgear::PathList;
using std::istream;
SGLockedQueue<SGPath> global_workQueue; SGLockedQueue<SGPath> global_workQueue;
/* /*
* Benchmark: Processing 800 individual buckets: * Benchmark: Processing 800 individual buckets:
* terrafit.cc: 52s 48s 48s * terrafit.cc: 52s 48s 48s
@ -73,38 +72,44 @@ SGLockedQueue<SGPath> global_workQueue;
* *
* terrafit.cc takes on 20% of the time that terrafit.py took! * terrafit.cc takes on 20% of the time that terrafit.py took!
*/ */
class ArrayMap: public Terra::Map { class ArrayMap : public Terra::Map {
public: public:
explicit ArrayMap(TGArray& array): array(array) { explicit ArrayMap(TGArray& array)
width=array.get_cols(); : array(array)
height=array.get_rows(); {
min=30000; width = array.get_cols();
max=-30000; height = array.get_rows();
for (int i=0;i<width;i++) { min = 30000;
for (int j=0;j<height;j++) { max = -30000;
Terra::real v=eval(i,j); for (int i = 0; i < width; i++) {
if (v<min) for (int j = 0; j < height; j++) {
min=v; Terra::real v = eval(i, j);
if (v>max) if (v < min)
max=v; min = v;
} if (v > max)
} max = v;
depth=32; }
} }
depth = 32;
}
virtual ~ArrayMap() {} virtual ~ArrayMap() {}
virtual Terra::real eval(int i, int j) override { virtual Terra::real eval(int i, int j) override
return (Terra::real)array.get_array_elev(i,j); {
} 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: protected:
TGArray& array; TGArray& array;
}; };
static Terra::ImportMask default_mask; static Terra::ImportMask default_mask;
@ -113,61 +118,57 @@ namespace Terra {
* don't need one... * don't need one...
*/ */
static Terra::ImportMask default_mask; static Terra::ImportMask default_mask;
Terra::ImportMask *MASK=&default_mask; Terra::ImportMask* MASK = &default_mask;
}; // namespace Terra }; // namespace Terra
Terra::real error_threshold=40.0; Terra::real error_threshold = 40.0;
unsigned int min_points=50; unsigned int min_points = 50;
unsigned int point_limit=1000; unsigned int point_limit = 1000;
bool force=false; bool force = false;
unsigned int num_threads = 1; unsigned int num_threads = 1;
inline int goal_not_met(Terra::GreedySubdivision* mesh) inline int goal_not_met(Terra::GreedySubdivision* mesh)
{ {
return return (mesh->maxError() > error_threshold && mesh->pointCount() < point_limit) || mesh->pointCount() < min_points;
( mesh->maxError() > error_threshold &&
mesh->pointCount() < point_limit ) ||
mesh->pointCount() < min_points;
} }
static void announce_goal(Terra::GreedySubdivision* mesh) static void announce_goal(Terra::GreedySubdivision* mesh)
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Goal conditions met:"); 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 << "]"); SG_LOG(SG_GENERAL, SG_INFO, " points=" << mesh->pointCount() << " [limit=" << point_limit << "]");
} }
void greedy_insertion(Terra::GreedySubdivision* mesh) void greedy_insertion(Terra::GreedySubdivision* mesh)
{ {
while (goal_not_met(mesh)) {
while( goal_not_met(mesh) ) if (!mesh->greedyInsert())
{
if( !mesh->greedyInsert() )
break; break;
} }
announce_goal(mesh); announce_goal(mesh);
} }
bool endswith(const std::string& s1, const std::string& suffix) { bool endswith(const std::string& s1, const std::string& suffix)
size_t s1len=s1.size(); {
size_t sufflen=suffix.size(); size_t s1len = s1.size();
size_t sufflen = suffix.size();
if (s1len<sufflen) { if (s1len < sufflen) {
return false; return false;
} }
return s1.compare(s1len-sufflen,sufflen,suffix)==0; return s1.compare(s1len - sufflen, sufflen, suffix) == 0;
} }
void fit_file(const SGPath& path) { void fit_file(const SGPath& path)
SG_LOG(SG_GENERAL, SG_INFO,"Working on file '" << path << "'"); {
SG_LOG(SG_GENERAL, SG_INFO, "Working on file '" << path << "'");
SGPath outPath(path.dir()); SGPath outPath(path.dir());
outPath.append(path.file_base() + ".fit.gz"); outPath.append(path.file_base() + ".fit.gz");
if ( outPath.exists() ) { if (outPath.exists()) {
unlink( outPath.c_str() ); unlink(outPath.c_str());
} }
SGBucket bucket; // dummy bucket SGBucket bucket; // dummy bucket
@ -182,22 +183,22 @@ void fit_file(const SGPath& path) {
greedy_insertion(&mesh); greedy_insertion(&mesh);
gzFile fp; gzFile fp;
if ( (fp = gzopen( outPath.c_str(), "wb9" )) == NULL ) { if ((fp = gzopen(outPath.c_str(), "wb9")) == NULL) {
SG_LOG(SG_GENERAL, SG_ALERT, "ERROR: opening " << outPath << " for writing!"); SG_LOG(SG_GENERAL, SG_ALERT, "ERROR: opening " << outPath << " for writing!");
return; return;
} }
gzprintf(fp,"%d\n",mesh.pointCount()); gzprintf(fp, "%d\n", mesh.pointCount());
for (int x=0;x<DEM.width;x++) { for (int x = 0; x < DEM.width; x++) {
for (int y=0;y<DEM.height;y++) { for (int y = 0; y < DEM.height; y++) {
if (mesh.is_used(x,y) != DATA_POINT_USED) if (mesh.is_used(x, y) != DATA_POINT_USED)
continue; continue;
double vx,vy,vz; double vx, vy, vz;
vx=(inarray.get_originx()+x*inarray.get_col_step())/3600.0; vx = (inarray.get_originx() + x * inarray.get_col_step()) / 3600.0;
vy=(inarray.get_originy()+y*inarray.get_row_step())/3600.0; vy = (inarray.get_originy() + y * inarray.get_row_step()) / 3600.0;
vz=DEM.eval(x,y); vz = DEM.eval(x, y);
gzprintf(fp,"%+03.8f %+02.8f %0.2f\n",vx,vy,vz); gzprintf(fp, "%+03.8f %+02.8f %0.2f\n", vx, vy, vz);
} }
} }
@ -211,7 +212,7 @@ void queue_fit_file(const SGPath& path)
if (!force) { if (!force) {
if (outPath.exists() && (path.modTime() < outPath.modTime())) { if (outPath.exists() && (path.modTime() < outPath.modTime())) {
SG_LOG(SG_GENERAL, SG_INFO ,"Skipping " << outPath << ", source " << path << " is older"); SG_LOG(SG_GENERAL, SG_INFO, "Skipping " << outPath << ", source " << path << " is older");
return; return;
} }
} }
@ -219,8 +220,7 @@ void queue_fit_file(const SGPath& path)
global_workQueue.push(path); global_workQueue.push(path);
} }
class FitThread : public SGThread class FitThread : public SGThread {
{
public: public:
virtual void run() virtual void run()
{ {
@ -233,15 +233,14 @@ public:
} }
}; };
void walk_path(const SGPath& path) { void walk_path(const SGPath& path)
{
if (!path.exists()) { if (!path.exists()) {
SG_LOG(SG_GENERAL, SG_ALERT ,"ERROR: Unable to stat '" << path.str() << "':" << strerror(errno)); SG_LOG(SG_GENERAL, SG_ALERT, "ERROR: Unable to stat '" << path.str() << "':" << strerror(errno));
return; return;
} }
if ((path.lower_extension() == "arr") || (path.complete_lower_extension() == "arr.rectified.gz") || if ((path.lower_extension() == "arr") || (path.complete_lower_extension() == "arr.rectified.gz") || (path.complete_lower_extension() == "arr.gz")) {
(path.complete_lower_extension() == "arr.gz")) {
SG_LOG(SG_GENERAL, SG_DEBUG, "will queue " << path); SG_LOG(SG_GENERAL, SG_DEBUG, "will queue " << path);
queue_fit_file(path); queue_fit_file(path);
} else if (path.isDir()) { } else if (path.isDir()) {
@ -253,86 +252,88 @@ void walk_path(const SGPath& path) {
} }
} }
void usage(char* progname, const std::string& msg) { void usage(char* progname, const std::string& msg)
if (msg.size()!=0) { {
SG_LOG(SG_GENERAL,SG_ALERT, msg); if (msg.size() != 0) {
SG_LOG(SG_GENERAL, SG_ALERT, msg);
} }
SG_LOG(SG_GENERAL,SG_INFO, "Usage: " << progname << " [options] <file | path to walk>"); SG_LOG(SG_GENERAL, SG_INFO, "Usage: " << progname << " [options] <file | path to walk>");
SG_LOG(SG_GENERAL,SG_INFO, "\t -h | --help"); 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 -m | --minnodes 50");
SG_LOG(SG_GENERAL,SG_INFO, "\t -x | --maxnodes 1000"); 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 -e | --maxerror 40");
SG_LOG(SG_GENERAL,SG_INFO, "\t -f | --force"); SG_LOG(SG_GENERAL, SG_INFO, "\t -f | --force");
SG_LOG(SG_GENERAL,SG_INFO, "\t -j | --threads <number>"); SG_LOG(SG_GENERAL, SG_INFO, "\t -j | --threads <number>");
SG_LOG(SG_GENERAL,SG_INFO, "\t -v | --version"); SG_LOG(SG_GENERAL, SG_INFO, "\t -v | --version");
SG_LOG(SG_GENERAL,SG_INFO, ""); SG_LOG(SG_GENERAL, SG_INFO, "");
SG_LOG(SG_GENERAL,SG_INFO, "Algorithm will produce at least <minnodes> fitted nodes, but no"); SG_LOG(SG_GENERAL, SG_INFO, "Algorithm will produce at least <minnodes> fitted nodes, but no");
SG_LOG(SG_GENERAL,SG_INFO, "more than <maxnodes>. Within that range, the algorithm will stop"); SG_LOG(SG_GENERAL, SG_INFO, "more than <maxnodes>. 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, "if the maximum elevation error for any remaining point");
SG_LOG(SG_GENERAL,SG_INFO, "drops below <maxerror> meters."); SG_LOG(SG_GENERAL, SG_INFO, "drops below <maxerror> meters.");
SG_LOG(SG_GENERAL,SG_INFO, ""); 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, "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, "will produce a better surface approximation.");
SG_LOG(SG_GENERAL,SG_INFO, ""); 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, "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, "by the hgtchop utility.");
SG_LOG(SG_GENERAL,SG_INFO, ""); 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, "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, "");
SG_LOG(SG_GENERAL,SG_INFO, "**** NOTE ****:"); 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, "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, "processed recursively.");
SG_LOG(SG_GENERAL,SG_INFO, ""); 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, "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, "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, ".fit.gz file will need to retriangulate the surface.");
} }
struct option options[]={ struct option options[] = {
{"help",no_argument,NULL,'h'}, { "help", no_argument, NULL, 'h' },
{"minnodes",required_argument,NULL,'m'}, { "minnodes", required_argument, NULL, 'm' },
{"maxnodes",required_argument,NULL,'x'}, { "maxnodes", required_argument, NULL, 'x' },
{"maxerror",required_argument,NULL,'e'}, { "maxerror", required_argument, NULL, 'e' },
{"force",no_argument,NULL,'f'}, { "force", no_argument, NULL, 'f' },
{"version",no_argument,NULL,'v'}, { "version", no_argument, NULL, 'v' },
{"threads",required_argument,NULL,'j'}, { "threads", required_argument, NULL, 'j' },
{NULL,0,NULL,0} { NULL, 0, NULL, 0 }
}; };
int main(int argc, char** argv) { int main(int argc, char** argv)
sglog().setLogLevels( SG_ALL, SG_INFO ); {
sglog().setLogLevels(SG_ALL, SG_INFO);
int option; int option;
auto start_time = std::chrono::high_resolution_clock::now(); 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) { switch (option) {
case 'h': case 'h':
usage(argv[0],""); usage(argv[0], "");
break; break;
case 'm': case 'm':
min_points=atoi(optarg); min_points = atoi(optarg);
break; break;
case 'x': case 'x':
point_limit=atoi(optarg); point_limit = atoi(optarg);
break; break;
case 'e': case 'e':
error_threshold=atof(optarg); error_threshold = atof(optarg);
break; break;
case 'f': case 'f':
force=true; force = true;
break; break;
case 'v': case 'v':
SG_LOG(SG_GENERAL,SG_INFO,argv[0] << " version " << getTGVersion()); SG_LOG(SG_GENERAL, SG_INFO, argv[0] << " version " << getTGVersion());
exit(0); exit(0);
break; break;
case 'j': case 'j':
num_threads = atoi(optarg); num_threads = atoi(optarg);
break; break;
case '?': case '?':
usage(argv[0],std::string("Unknown option:")+(char)optopt); usage(argv[0], std::string("Unknown option:") + (char)optopt);
exit(1); 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 points = " << point_limit);
SG_LOG(SG_GENERAL, SG_INFO, "Max error = " << error_threshold); SG_LOG(SG_GENERAL, SG_INFO, "Max error = " << error_threshold);
if (optind<argc) { if (optind < argc) {
while (optind<argc) { while (optind < argc) {
SG_LOG(SG_GENERAL, SG_INFO, "walking " << SGPath(argv[optind])); SG_LOG(SG_GENERAL, SG_INFO, "walking " << SGPath(argv[optind]));
walk_path(SGPath(argv[optind++])); walk_path(SGPath(argv[optind++]));
} }
@ -351,8 +352,8 @@ int main(int argc, char** argv) {
exit(1); exit(1);
} }
std::vector<std::shared_ptr<FitThread> > threads; std::vector<std::shared_ptr<FitThread>> threads;
for (unsigned int t=0; t<num_threads; ++t) { for (unsigned int t = 0; t < num_threads; ++t) {
std::shared_ptr<FitThread> thread(new FitThread); std::shared_ptr<FitThread> thread(new FitThread);
thread->start(); thread->start();
threads.push_back(thread); threads.push_back(thread);
@ -362,7 +363,7 @@ int main(int argc, char** argv) {
sleep(1); sleep(1);
} }
for (unsigned int t=0; t<num_threads; ++t) { for (unsigned int t = 0; t < num_threads; ++t) {
threads[t]->join(); threads[t]->join();
} }
@ -370,7 +371,9 @@ int main(int argc, char** argv) {
auto finish_time = std::chrono::high_resolution_clock::now(); auto finish_time = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish_time - start_time; std::chrono::duration<double> 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; return EXIT_SUCCESS;
} }