initial upload

This commit is contained in:
2024-09-10 20:25:18 +08:00
parent b8de03ee4f
commit f1cc876972
377 changed files with 2721267 additions and 34 deletions

View File

@@ -0,0 +1,5 @@
add_executable(trackline main.cpp)
# 第二种方式指定目标文件的路径 这个方式目标文件夹中将只包含目标文件而没有中间文件
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 设置安装地址
install(TARGETS trackline RUNTIME DESTINATION selfpro)

View File

@@ -0,0 +1,87 @@
#include "trackLine.h"
void disp_help()
{
cout << "trackline - v1.1 extract data along a line from a group of 2-D data points" << endl
<< "Author: zhangyi.cugwuhan@gmail.com" << endl << endl
<< "usage: trackline -i<input-file>[+d<x-col>,<y-col>,<z-col>] -o<output-file> \n\t -l<input-file>[+d<x-col>,<y-col>]|<p1-x>/<p1-y>/<p2-x>/<p2-y>/<spacing> \n\t [-b<grid-x>/<grid-y>] [-h]" << endl
<< "\t-i\tinput data table. a +d option could be attached to the filename to select data columns of the input data, the default is 0,1,2. Note that any line starts with '#' will be skipped" << endl
<< "\t-o\toutput data table, every line contains a x-coordinate of a point on the line and 2-D coordinates of the point, and the point's value" << endl
<< "\t-l\tline parameters, you can either specify where the line starts and ends, plus interval of data points on the line. Or you can give point locations via a file, a +d option could be attached to the filename to select data columns of the input data, the default is 0,1. Note that any line starts with '#' will be skipped" << endl
<< "\t-b\tgriding parameters, the program will automatically using the mean area-size of input points to estimate a griding size if no -b option has been set" << endl
<< "\t-h\tshow this info" << endl;
}
int main(int argc, char** argv)
{
trackLine tl;
char infilename[1024] = "NULL";
char outfilename[1024] = "NULL";
char boxpara[1024] = "NULL";
char linepara[1024] = "NULL";
opterr = 0; //内置参数 若不为0则会在发生遭遇错误时输出一条信息到屏幕
int curr;
/*循环拾取参数 最后一个参数为-1 需要变量的参数后跟一个冒号 可有可无参数跟两个冒号*/
while((curr = getopt(argc,argv,"hi:o:l:b:")) != -1)
{
/*匹配命令*/
switch (curr)
{
case 'h': //显示帮助信息
disp_help();
break;
case 'i':
if (1!=sscanf(optarg,"%s",infilename))
{
cout << "error ==> wrong format of " << optarg << endl;
}
break;
case 'o':
if (1!=sscanf(optarg,"%s",outfilename))
{
cout << "error ==> wrong format of " << optarg << endl;
}
break;
case 'l':
if (1!=sscanf(optarg,"%s",linepara))
{
cout << "error ==> wrong format of " << optarg << endl;
}
break;
case 'b':
if (1!=sscanf(optarg,"%s",boxpara))
{
cout << "error ==> wrong format of " << optarg << endl;
}
break;
case '?': //处理未定义或错误参数
if (optopt == 'i' || optopt == 'o' || optopt == 'l' || optopt == 'b')
{
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
return -1;
}
else if (isprint(optopt))
{
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
return -1;
}
else
{
fprintf (stderr,"Unknown option character `\\x%x'.\n",optopt);
return -1;
}
break;
default:
abort();
}
}
if (tl.getInputNode(infilename)) return 0;
tl.initBox(boxpara);
if (tl.initLine(linepara)) return 0;
tl.interLine();
tl.outLine(outfilename);
return 0;
}

View File

@@ -0,0 +1,15 @@
CC = g++-7
PROM = /usr/local/sbin/trackline
CFLAGS = -I.
DEPS = $(shell find . -name "*.h")
SRC = $(shell find . -name "*.cpp")
OBJ = $(SRC:%.cpp=%.o)
$(PROM): $(OBJ)
$(CC) -o $(PROM) $(OBJ) $(CFLAGS)
%.o:%.cpp $(DEPS)
$(CC) -c $< -o $@ $(CFLAGS)
clean:
rm -rf $(OBJ)

View File

@@ -0,0 +1,5 @@
### 二维平面数据提取剖面
输入数据自由网或者规则网的二维平面数据一般每个数据点位包含xy坐标和数据值即可不对数据分布与外接轮廓形状做要求。
输出数据:一条剖面上的数据,剖面一般为一条线段,必要的参数包括始终点位置与剖面上的数据间隔。

View File

@@ -0,0 +1,119 @@
#ifndef _SYSDEFINE_H
#define _SYSDEFINE_H
#include "ctype.h"
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "string.h"
#include "iostream"
#include "fstream"
#include "sstream"
#include "iomanip"
#include "vector"
#include "ctime"
#include "cmath"
#define ZERO 1.0e-16
#define BDL_MAX 1.0e+30
#define BDL_MIN -1.0e+30
#define BOLDRED "\033[1m\033[31m"
#define RESET "\033[0m"
#define pi (4.0*atan(1.0))
using namespace std;
typedef vector<int> _1iArray;
typedef vector<vector<int> > _2iArray;
typedef vector<double> _1dArray;
int open_infile(ifstream &infile,char* filename)
{
infile.open(filename);
if (!infile)
{
cout << BOLDRED << "error ==> " << RESET << "file not found: " << filename << endl;
return -1;
}
return 0;
}
int open_outfile(ofstream &outfile,char* filename)
{
outfile.open(filename);
if (!outfile)
{
cout << BOLDRED << "error ==> " << RESET << "fail to create the file: " << filename << endl;
return -1;
}
return 0;
}
struct node2d
{
int id;
double px; //切割剖面上的二维横纵坐标值
double x,y; //在球坐标数据插值中 x y值对应经纬度 z值对应深度
double val; //目前只允许每个点附带一个数据值
node2d()
{
id = -1;
x = y = val = BDL_MAX;
px = BDL_MAX;
}
void info()
{
cout << id << " " << x << " " << y << " " << px << " " << val << endl;
}
};
typedef vector<node2d> node2dArray;
double node2dDistance(node2d n1,node2d n2)
{
return sqrt(pow(n2.x-n1.x,2)+pow(n2.y-n1.y,2));
}
//规则网络插值 长方形内数据插值 距离平方反比
/*长方体示意图*/
// y
// |
// |
// 3------------2
// | |
// | |
// | |
// 0------------1--->x
// 左下角坐标x0 y0
// 块体尺寸dx dy
// 插值点坐标x y
// 四个角点值
double interRectDist(double x0,double y0,double dx,double dy,double x,double y,
double d0,double d1,double d2,double d3)
{
double res = 0;
double total_dist = 0;
double dist[4] = {0,0,0,0};
double val[4];
val[0] = d0; val[1] = d1; val[2] = d2; val[3] = d3;
//检查四个角点值 如果有一个角点值为1e+30 则无法插值 返回插值点值为1e+30
for (int i = 0; i < 4; i++)
{
if (val[i] == BDL_MAX)
{
return BDL_MAX;
}
}
dist[0] = 1.0/(1e-30+(x-x0)*(x-x0)+(y-y0)*(y-y0));
dist[1] = 1.0/(1e-30+(x-dx-x0)*(x-dx-x0)+(y-y0)*(y-y0));
dist[2] = 1.0/(1e-30+(x-dx-x0)*(x-dx-x0)+(y-dy-y0)*(y-dy-y0));
dist[3] = 1.0/(1e-30+(x-x0)*(x-x0)+(y-dy-y0)*(y-dy-y0));
for (int i = 0; i < 4; i++)
{
total_dist += dist[i];
}
for (int i = 0; i < 4; i++)
{
res += val[i]*dist[i]/total_dist;
}
return res;
}
#endif

View File

@@ -0,0 +1,350 @@
#ifndef _TRACKLINE_H
#define _TRACKLINE_H
#include "sysDefine.h"
class trackLine
{
public:
trackLine(){}
~trackLine(){}
int getInputNode(char*);
int initBox(char*);
int initLine(char*);
int interLine();
int outLine(char*);
private:
node2dArray inputNode;
node2dArray lineNode;
int xnum,ynum;
double dx,dy;
double xmin,xmax,ymin,ymax;
_2iArray boxIndex;
node2dArray boxNode;
};
int trackLine::getInputNode(char* para)
{
char order[1024] = "0,1,2";
char filename[1024] = "NULL";
int orders[3];
double temp_d;
_1dArray tempRow;
string temp_str;
stringstream temp_ss;
//首先尝试分离文件名和+d命令
if (2 != sscanf(para,"%[^+]+d%s",filename,order))
{
//分离失败 直接将para解释为文件名
strcpy(filename,para);
}
ifstream datain;
if(open_infile(datain,filename)) return -1;
if (3 != sscanf(order,"%d,%d,%d",&orders[0],&orders[1],&orders[2]))
{
cout << BOLDRED << "error ==> " << RESET << "wrong order parameters for the file: " << filename << endl;
return -1;
}
node2d tempNode;
while(getline(datain,temp_str))
{
if(*(temp_str.begin()) == '#') continue;
temp_ss.clear();
temp_ss << temp_str;
//解析数据行
if(!tempRow.empty()) tempRow.clear();
while (temp_ss >> temp_d)
{
tempRow.push_back(temp_d);
}
//读入指定位置的数据
tempNode.x = tempRow.at(orders[0]);
tempNode.y = tempRow.at(orders[1]);
tempNode.val = tempRow.at(orders[2]);
tempNode.id = inputNode.size();
inputNode.push_back(tempNode);
}
datain.close();
return 0;
}
int trackLine::initBox(char* para)
{
//定位二维点位的中心位置
xmin = ymin = BDL_MAX;
xmax = ymax = BDL_MIN;
for (int i = 0; i < inputNode.size(); i++)
{
if (inputNode.at(i).x < xmin) xmin = inputNode.at(i).x;
if (inputNode.at(i).x > xmax) xmax = inputNode.at(i).x;
if (inputNode.at(i).y < ymin) ymin = inputNode.at(i).y;
if (inputNode.at(i).y > ymax) ymax = inputNode.at(i).y;
}
double cx,cy;
cx = 0.5*(xmin+xmax); cy = 0.5*(ymin+ymax);
//确定盒子的边长
double pointArea;
/*这里我们发现使用任意两点间的最短距离作为自动网格化大小并不能取得很好的效果
经常可能会造成插值点无值的状况 因此我们这里将使用平均点位面积估算网格大小 效果出众 而且这样做仅需要很少的运算*/
if (2 != sscanf(para,"%lf/%lf",&dx,&dy))
{
pointArea = (xmax-xmin)*(ymax-ymin)/inputNode.size();
dx = dy = sqrt(pointArea);
}
//确定盒子在x和y方向的半盒子数 向上取整
int halfNum_x = ceil((xmax-cx)/dx);
int halfNum_y = ceil((ymax-cy)/dy);
//重新确定盒子的范围 向外推出一层
xmin = cx - halfNum_x*dx - dx;
xmax = cx + halfNum_x*dx + dx;
ymin = cy - halfNum_y*dy - dy;
ymax = cy + halfNum_y*dy + dy;
//确定盒子在x和y方向的盒子数
xnum = int ((xmax-xmin)/dx);
ynum = int ((ymax-ymin)/dy);
//初始化盒子上的节点
node2d tempNode;
for (int j = 0; j < ynum+1; j++)
{
for (int k = 0; k < xnum+1; k++)
{
tempNode.x = xmin + k*dx;
tempNode.y = ymin + j*dy;
tempNode.val = BDL_MAX;
tempNode.id = boxNode.size();
boxNode.push_back(tempNode);
}
}
//将输入点位放置在盒子中
int temp_m,temp_n;
boxIndex.resize(xnum*ynum);
for (int i = 0; i < inputNode.size(); i++)
{
temp_m = floor((inputNode.at(i).x - xmin)/dx);
temp_n = floor((inputNode.at(i).y - ymin)/dy);
boxIndex.at(temp_n*xnum+temp_m).push_back(inputNode.at(i).id);
}
//查看每个盒子节点周围四个盒子中的输入点 插值确定盒子节点上的值
double tempRes,oneDist,totalDist;
int rectIndex;
int nodeIndex;
for (int j = 0; j < ynum-1; j++)
{
for (int k = 0; k < xnum-1; k++)
{
tempRes = 0;
totalDist = 0;
nodeIndex = (j+1)*(xnum+1)+k+1;
//查看四个格子内的顶点 并利用距离平方反比插值
for (int n = 0; n < 2; n++)
{
for (int p = 0; p < 2; p++)
{
rectIndex = (j+n)*xnum+k+p;
if (!boxIndex.at(rectIndex).empty())
{
for (int b = 0; b < boxIndex.at(rectIndex).size(); b++)
{
totalDist +=
1.0/(1e-30
+pow(inputNode.at(boxIndex.at(rectIndex).at(b)).x - boxNode.at(nodeIndex).x,2)
+pow(inputNode.at(boxIndex.at(rectIndex).at(b)).y - boxNode.at(nodeIndex).y,2));
}
}
}
}
if (totalDist == 0)
{
boxNode.at(nodeIndex).val = BDL_MAX;
continue;
}
//计算插值
for (int n = 0; n < 2; n++)
{
for (int p = 0; p < 2; p++)
{
rectIndex = (j+n)*xnum+k+p;
if (!boxIndex.at(rectIndex).empty())
{
for (int b = 0; b < boxIndex.at(rectIndex).size(); b++)
{
oneDist =
1.0/(1e-30
+pow(inputNode.at(boxIndex.at(rectIndex).at(b)).x - boxNode.at(nodeIndex).x,2)
+pow(inputNode.at(boxIndex.at(rectIndex).at(b)).y - boxNode.at(nodeIndex).y,2));
tempRes += inputNode.at(boxIndex.at(rectIndex).at(b)).val*oneDist/totalDist;
}
}
}
}
boxNode.at(nodeIndex).val = tempRes;
}
}
return 0;
}
int trackLine::initLine(char* para)
{
char order[1024] = "0,1";
char filename[1024] = "NULL";
int orders[2];
double temp_d;
_1dArray tempRow;
string temp_str;
stringstream temp_ss;
node2d tempNode;
double length;
double xinterval;
node2d n1,n2,snode,enode;
//首先尝试从参数初始化待插值点
if (5 == sscanf(para,"%lf/%lf/%lf/%lf/%lf",&n1.x,&n1.y,&n2.x,&n2.y,&xinterval))
{
snode = n1; enode = n2;
//计算水平方向剖面长度
double plen = sqrt(pow(enode.x-snode.x,2)+pow(enode.y-snode.y,2));
length = 0;
while(length <= plen)
{
tempNode.x = snode.x+(enode.x-snode.x)*length/plen;
tempNode.y = snode.y+(enode.y-snode.y)*length/plen;
tempNode.px = length;
tempNode.id = lineNode.size();
lineNode.push_back(tempNode);
length += xinterval;
}
}
//首先尝试分离文件名和+d命令
else if (2 == sscanf(para,"%[^+]+d%s",filename,order))
{
ifstream datain;
if(open_infile(datain,filename)) return -1;
if (2 != sscanf(order,"%d,%d",&orders[0],&orders[1]))
{
cout << BOLDRED << "error ==> " << RESET << "wrong order parameters for the file: " << filename << endl;
return -1;
}
while(getline(datain,temp_str))
{
if(*(temp_str.begin()) == '#') continue;
temp_ss.clear();
temp_ss << temp_str;
//解析数据行
if(!tempRow.empty()) tempRow.clear();
while (temp_ss >> temp_d)
{
tempRow.push_back(temp_d);
}
//读入指定位置的数据
tempNode.x = tempRow.at(orders[0]);
tempNode.y = tempRow.at(orders[1]);
tempNode.id = lineNode.size();
lineNode.push_back(tempNode);
}
datain.close();
//计算待插值点在剖面上的累积长度
length = 0;
lineNode.at(0).px = 0.0;
for (int i = 1; i < lineNode.size(); i++)
{
length += node2dDistance(lineNode.at(i-1),lineNode.at(i));
lineNode.at(i).px = length;
}
}
//分离失败 直接将para解释为文件名
else
{
strcpy(filename,para);
ifstream datain;
if(open_infile(datain,filename)) return -1;
while(getline(datain,temp_str))
{
if(*(temp_str.begin()) == '#') continue;
temp_ss.clear();
temp_ss << temp_str;
//解析数据行
if(!tempRow.empty()) tempRow.clear();
while (temp_ss >> temp_d)
{
tempRow.push_back(temp_d);
}
//读入指定位置的数据
tempNode.x = tempRow.at(orders[0]);
tempNode.y = tempRow.at(orders[1]);
tempNode.id = lineNode.size();
lineNode.push_back(tempNode);
}
datain.close();
//计算待插值点在剖面上的累积长度
length = 0;
lineNode.at(0).px = 0.0;
for (int i = 1; i < lineNode.size(); i++)
{
length += node2dDistance(lineNode.at(i-1),lineNode.at(i));
lineNode.at(i).px = length;
}
}
return 0;
}
int trackLine::interLine()
{
int temp_m,temp_n;
for (int i = 0; i < lineNode.size(); i++)
{
//检查待插值点的位置是否在盒子内
if (lineNode.at(i).x < xmin + dx ||
lineNode.at(i).x > xmax - dx ||
lineNode.at(i).y < ymin + dy ||
lineNode.at(i).y > ymax - dy)
{
lineNode.at(i).val = BDL_MAX;
continue;
}
temp_m = floor((lineNode.at(i).x - xmin)/dx);
temp_n = floor((lineNode.at(i).y - ymin)/dy);
lineNode.at(i).val = interRectDist(xmin+temp_m*dx,ymin+temp_n*dy,dx,dy,
lineNode.at(i).x,lineNode.at(i).y,
boxNode.at(temp_n*(xnum+1)+temp_m).val,
boxNode.at(temp_n*(xnum+1)+temp_m+1).val,
boxNode.at((temp_n+1)*(xnum+1)+temp_m+1).val,
boxNode.at((temp_n+1)*(xnum+1)+temp_m).val);
}
return 0;
}
int trackLine::outLine(char* filename)
{
time_t now = time(0);
char* dt = ctime(&now);
ofstream lineOut;
if (open_outfile(lineOut,filename)) return -1;
lineOut << "# This file is generated by trackLine on " << dt;
lineOut << "# For more information please contact the author via: zhangyi.cugwuhan@gmail.com" << endl;
lineOut << "# XonLine XonPlane YonPlane Val" << endl;
for (int i = 0; i < lineNode.size(); i++)
{
if (lineNode.at(i).val == BDL_MAX)
{
lineOut << lineNode.at(i).px << " " << lineNode.at(i).x << " " << lineNode.at(i).y << " NaN" << endl;
}
else lineOut << lineNode.at(i).px << " " << lineNode.at(i).x << " " << lineNode.at(i).y << " " << lineNode.at(i).val << endl;
}
lineOut.close();
return 0;
}
#endif