gctl_toolkits/archive/gmt2msh/func.h
2024-09-10 20:25:18 +08:00

274 lines
6.1 KiB
C++

#include "iostream"
#include "fstream"
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "sstream"
#include "vector"
#include "string.h"
#include "cmath"
#include "iomanip"
#include "map"
#define WGS84_PoleRadius 6356752.3//WGS84椭球极半径
#define WGS84_EquatorRadius 6378137//WGS84椭球长半径
#define EarthRadius 6371008.8
#define Pi (4.0*atan(1.0))
#define BOLDRED "\033[1m\033[31m"
#define RESET "\033[0m"
#define MAX_DBL 1e+30
#define ZERO 1e-20
using namespace std;
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;
}
//计算一个参考椭球或者参考球在纬度位置的半径
double refRadius(double lati,double refr,double refR)
{
return refr*refR/sqrt(pow(refr,2)*pow(cos((double) lati*Pi/180.0),2)+pow(refR,2)*pow(sin((double) lati*Pi/180.0),2));
}
//直角坐标系下的一个点
struct cpoint
{
double x,y,z;
cpoint() //初始化坐标值
{
x = y = z = MAX_DBL;
}
};
//球坐标系下的一个点
struct spoint
{
double lon,lat,rad;
spoint() //初始化坐标值
{
lon = lat = rad = MAX_DBL;
}
};
/*直角坐标与球坐标相互转换函数 注意这里使用的球坐标是地理坐标范围 即经度为-180~180 纬度为-90~90*/
cpoint s2c(spoint s)
{
cpoint c;
c.x = s.rad*sin((0.5 - s.lat/180.0)*Pi)*cos((2.0 + s.lon/180.0)*Pi);
c.y = s.rad*sin((0.5 - s.lat/180.0)*Pi)*sin((2.0 + s.lon/180.0)*Pi);
c.z = s.rad*cos((0.5 - s.lat/180.0)*Pi);
return c;
}
spoint c2s(cpoint c)
{
spoint s;
s.rad = sqrt(pow(c.x,2)+pow(c.y,2)+pow(c.z,2));
if (fabs(s.rad)<ZERO) //点距离原点极近 将点置于原点
{
s.lat = s.lon = 0.0;
}
else
{
s.lat = 90.0 - acos(c.z/s.rad)*180.0/Pi;
s.lon = atan2(c.y,c.x)*180.0/Pi;
}
return s;
}
struct node
{
int id;
cpoint posic; //直角坐标系位置
spoint posis; //球坐标系位置
void set(cpoint c) //从直角坐标位置初始化
{
posic.x = c.x; posic.y = c.y; posic.z = c.z;
posis = c2s(posic);
}
void set(spoint s) //从球坐标位置初始化
{
posis.lon = s.lon; posis.lat = s.lat; posis.rad = s.rad;
posic = s2c(posis);
}
};
typedef vector<node> nodeArray;
typedef map<string,int> strMap; //顶点位置映射 用于通过顶点位置寻找相应顶点
struct triangle
{
int id;
int index[3];
};
typedef vector<triangle> triArray;
class gmt2msh
{
public:
gmt2msh(){}
~gmt2msh(){}
int getRef(char*);
int getNode(char*,double,double);
int getNode(char*,double);
int outMsh(char*);
private:
double refr,refR;
nodeArray Nodes;
strMap mapStr;
strMap::iterator ivm;
triArray Triangles;
};
int gmt2msh::getRef(char* para)
{
//首先匹配预定义类型
if (!strcmp(para,"WGS84"))
{
refr = WGS84_PoleRadius;
refR = WGS84_EquatorRadius;
}
else if (!strcmp(para,"EarthRadius"))
{
refr = EarthRadius;
refR = EarthRadius;
}
//匹配参数格式
else if (2 == sscanf(para,"%lf/%lf",&refr,&refR))
{
if (refr <= 0 || refR <= 0)
{
cout << BOLDRED << "Error ==> " << RESET << "fail to initial reference system" << endl;
return -1;
}
}
else
{
cout << BOLDRED << "Error ==> " << RESET << "fail to initial reference system" << endl;
return -1;
}
return 0;
}
int gmt2msh::getNode(char* filename,double refr,double refR)
{
ifstream infile;
if (open_infile(infile,filename)) return -1;
string temp_str;
stringstream temp_ss;
node temp_node;
triangle temp_tri;
while (getline(infile,temp_str))
{
if (*(temp_str.begin()) == '#') continue;
if (1 == sscanf(temp_str.c_str(),"> Triangle: %d",&temp_tri.id))
{
for (int i = 0; i < 3; i++)
{
getline(infile,temp_str);
temp_ss.str("");
temp_ss.clear();
temp_ss << temp_str;
temp_ss >> temp_node.posis.lon >> temp_node.posis.lat;
temp_node.posis.rad = refRadius(temp_node.posis.lat,refr,refR);
temp_node.set(temp_node.posis);
//查找映射表
ivm = mapStr.find(temp_str);
if (ivm == mapStr.end())
{
temp_node.id = Nodes.size();
Nodes.push_back(temp_node);
temp_tri.index[i] = temp_node.id;
//添加映射
mapStr[temp_str] = temp_node.id;
}
else temp_tri.index[i] = ivm->second;
}
}
Triangles.push_back(temp_tri);
}
infile.close();
}
int gmt2msh::getNode(char* filename,double alti)
{
ifstream infile;
if (open_infile(infile,filename)) return -1;
string temp_str;
stringstream temp_ss;
node temp_node;
triangle temp_tri;
while (getline(infile,temp_str))
{
if (*(temp_str.begin()) == '#') continue;
if (sscanf(temp_str.c_str(),"> Triangle: %d",&temp_tri.id))
{
for (int i = 0; i < 3; i++)
{
getline(infile,temp_str);
temp_ss.str("");
temp_ss.clear();
temp_ss << temp_str;
temp_ss >> temp_node.posic.x >> temp_node.posic.y;
temp_node.posic.z = alti;
temp_node.set(temp_node.posic);
//查找映射表
ivm = mapStr.find(temp_str);
if (ivm == mapStr.end())
{
temp_node.id = Nodes.size();
Nodes.push_back(temp_node);
temp_tri.index[i] = temp_node.id;
//添加映射
mapStr[temp_str] = temp_node.id;
}
else temp_tri.index[i] = ivm->second;
}
}
Triangles.push_back(temp_tri);
}
infile.close();
}
int gmt2msh::outMsh(char* filename)
{
ofstream outfile;
if(open_outfile(outfile,filename)) return -1;
outfile<<"$MeshFormat"<<endl<<"2.2 0 8"<<endl<<"$EndMeshFormat"<<endl<<"$Nodes"<<endl<<Nodes.size()<<endl;
for (int i = 0; i < Nodes.size(); i++)
{
outfile << Nodes.at(i).id << " " << setprecision(16) << Nodes.at(i).posic.x << " " << Nodes.at(i).posic.y << " " << Nodes.at(i).posic.z << endl;
}
outfile<<"$EndNodes"<<endl<<"$Elements"<<endl<<Triangles.size()<<endl;
for (int i = 0; i < Triangles.size(); i++)
{
outfile<< Triangles.at(i).id <<" 2 1 0 " << Triangles.at(i).index[0] << " " << Triangles.at(i).index[1] << " " << Triangles.at(i).index[2] << endl;
}
outfile<<"$EndElements"<<endl;
outfile.close();
return 0;
}