274 lines
6.1 KiB
C++
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;
|
|
} |