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 <string>
#include <stdio.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#ifndef _MSC_VER
# include <unistd.h>
# ifdef __APPLE__
# include <Prep/Terra/getopt.h>
# else
# include <getopt.h>
# endif
#include <unistd.h>
#ifdef __APPLE__
#include <Prep/Terra/getopt.h>
#else
# define S_ISDIR(a) ((a)&_S_IFDIR)
# include <windows.h>
# include <Prep/Terra/getopt.h>
# define sleep(x) Sleep(x*1000)
#include <getopt.h>
#endif
#else
#define S_ISDIR(a) ((a)&_S_IFDIR)
#include <Prep/Terra/getopt.h>
#include <windows.h>
#define sleep(x) Sleep(x * 1000)
#endif
#include <zlib.h>
#include <simgear/debug/logstream.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_path.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/threads/SGQueue.hxx>
#include <simgear/threads/SGThread.hxx>
@ -59,13 +59,12 @@
#include <Prep/Terra/Map.h>
#include <Prep/Terra/Mask.h>
using std::istream;
using simgear::Dir;
using simgear::PathList;
using std::istream;
SGLockedQueue<SGPath> global_workQueue;
/*
* Benchmark: Processing 800 individual buckets:
* 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!
*/
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;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;
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<sufflen) {
if (s1len < sufflen) {
return false;
}
return s1.compare(s1len-sufflen,sufflen,suffix)==0;
return s1.compare(s1len - sufflen, sufflen, suffix) == 0;
}
void fit_file(const SGPath& path) {
SG_LOG(SG_GENERAL, SG_INFO,"Working on file '" << path << "'");
void fit_file(const SGPath& path)
{
SG_LOG(SG_GENERAL, SG_INFO, "Working on file '" << path << "'");
SGPath outPath(path.dir());
outPath.append(path.file_base() + ".fit.gz");
if ( outPath.exists() ) {
unlink( outPath.c_str() );
if (outPath.exists()) {
unlink(outPath.c_str());
}
SGBucket bucket; // dummy bucket
@ -182,22 +183,22 @@ void fit_file(const SGPath& path) {
greedy_insertion(&mesh);
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!");
return;
}
gzprintf(fp,"%d\n",mesh.pointCount());
gzprintf(fp, "%d\n", mesh.pointCount());
for (int x=0;x<DEM.width;x++) {
for (int y=0;y<DEM.height;y++) {
if (mesh.is_used(x,y) != DATA_POINT_USED)
for (int x = 0; x < DEM.width; x++) {
for (int y = 0; y < DEM.height; y++) {
if (mesh.is_used(x, y) != DATA_POINT_USED)
continue;
double vx,vy,vz;
vx=(inarray.get_originx()+x*inarray.get_col_step())/3600.0;
vy=(inarray.get_originy()+y*inarray.get_row_step())/3600.0;
vz=DEM.eval(x,y);
gzprintf(fp,"%+03.8f %+02.8f %0.2f\n",vx,vy,vz);
double vx, vy, vz;
vx = (inarray.get_originx() + x * inarray.get_col_step()) / 3600.0;
vy = (inarray.get_originy() + y * inarray.get_row_step()) / 3600.0;
vz = DEM.eval(x, y);
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 (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;
}
}
@ -219,8 +220,7 @@ void queue_fit_file(const SGPath& path)
global_workQueue.push(path);
}
class FitThread : public SGThread
{
class FitThread : public SGThread {
public:
virtual void run()
{
@ -233,15 +233,14 @@ public:
}
};
void walk_path(const SGPath& path) {
void walk_path(const SGPath& path)
{
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;
}
if ((path.lower_extension() == "arr") || (path.complete_lower_extension() == "arr.rectified.gz") ||
(path.complete_lower_extension() == "arr.gz")) {
if ((path.lower_extension() == "arr") || (path.complete_lower_extension() == "arr.rectified.gz") || (path.complete_lower_extension() == "arr.gz")) {
SG_LOG(SG_GENERAL, SG_DEBUG, "will queue " << path);
queue_fit_file(path);
} else if (path.isDir()) {
@ -253,86 +252,88 @@ void walk_path(const SGPath& path) {
}
}
void usage(char* progname, const std::string& msg) {
if (msg.size()!=0) {
SG_LOG(SG_GENERAL,SG_ALERT, msg);
void usage(char* progname, const std::string& 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, "\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 <number>");
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 <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, "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, "");
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] <file | path to walk>");
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 <number>");
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 <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, "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, "");
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<argc) {
while (optind<argc) {
if (optind < argc) {
while (optind < argc) {
SG_LOG(SG_GENERAL, SG_INFO, "walking " << SGPath(argv[optind]));
walk_path(SGPath(argv[optind++]));
}
@ -351,8 +352,8 @@ int main(int argc, char** argv) {
exit(1);
}
std::vector<std::shared_ptr<FitThread> > threads;
for (unsigned int t=0; t<num_threads; ++t) {
std::vector<std::shared_ptr<FitThread>> threads;
for (unsigned int t = 0; t < num_threads; ++t) {
std::shared_ptr<FitThread> 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; t<num_threads; ++t) {
for (unsigned int t = 0; t < num_threads; ++t) {
threads[t]->join();
}
@ -370,7 +371,9 @@ int main(int argc, char** argv) {
auto finish_time = std::chrono::high_resolution_clock::now();
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;
}