GPS数据提取解析源码GPS source data extraction analysis, we can refer to learn from
GPS数据解析
数据拆分 \坐标转换 \显示线路图\源代码
逐条读取gps数据 然后进行拆分 解析,坐标转换,绘制线路。。。很好的示例多多交流学习。。
本程序是基于VC++ 建立的单文档工程。
废话少说,直接上代码
//获取子字符串个数
int GetSubStrCount(CString str,char cFlag)
{
cFlag = ',';
int i = 0;
BOOL isHas = FALSE;
for (int iStart = -1; -1 != (iStart = str.Find(cFlag,iStart+1)) ; i++)
{
isHas = TRUE;
}
if (!isHas)
{
return 0;
}
else
{
return i+1;
}
}
//获取子字符串
// i 序号 0
CString GetSubStr(CString str,int i,char cFlag)
{
cFlag = ',';
int iStart = -1;
int iEnd = 0;
int j = 0;
int iStrCount;
iStrCount = GetSubStrCount(str,cFlag);
if (i>iStrCount -1 || i<0)
{
str = "";
return str;
}
else
{
//do nothing
}
if (i == iStrCount-1)
{
i = iStrCount;
for (;j
{
iStart = str.Find(cFlag , iStart+1);
}
return str.Mid(iStart+1 , str.GetLength()-iStart-1);
}
else
{
//do nothing
}
for (; j
{
iStart = str.Find(cFlag , iStart+1);
}
iEnd = str.Find(cFlag , iStart+1);
return str.Mid(iStart+1 , iEnd-iStart-1);
}
//数据解析
CString CGpsDataView::Analyzing(CString str)
{
CString subStr[20];
char cFlag = ',';
int j = GetSubStrCount(str,cFlag); //得到该行的子字符串个数
CStdioFile wFile;
wFile.Open("save.txt",CFile::modeCreate | CFile::modeWrite | CFile::typeText);//将数据写入文件
for (int i=0;i
{
subStr[i] = GetSubStr(str,i,cFlag);
}
//GPGGA数据
if (subStr[0] == "$GPGGA")
{
CoordCovert(subStr[2],subStr[4]);
//提取时间
subStr[1].Insert(2,':');
subStr[1].Insert(5,':');
subStr[1].Insert(0," UTC时间:");
//提取纬度
if (subStr[3] == 'N')
{
subStr[2].Insert(11,"分");
subStr[2].Insert(2,"度");
subStr[2].Insert(0," 北纬");
}
else if (subStr[3] == 'S')
{
subStr[2].Insert(11,"分");
subStr[2].Insert(2,"度");
subStr[2].Insert(0," 南纬");
}
//提取经度
if (subStr[5] == 'E')
{
subStr[4].Insert(12,"分");
subStr[4].Insert(3,"度");
subStr[4].Insert(0," 东经");
}
else if (subStr[5] == 'W')
{
subStr[4].Insert(12,"分");
subStr[4].Insert(3,"度");
subStr[4].Insert(0," 西经");
}
//判断GPS状态
CString GpsState;
if (subStr[6] == '0')
{
GpsState = " GPS状态:无定位.";
}
else if (subStr[6] == '1')
{
GpsState = " GPS状态:无差分校正定位.";
}
else if (subStr[6] == '2')
{
GpsState = " GPS状态:差分校正定位.";
}
else if (subStr[6] == '9')
{
GpsState = " GPS状态:用星历计算定位.";
}
//提取卫星数
subStr[7].Insert(0," 卫星数:");
//提取平面位置精度因子
subStr[8].Insert(0," 平面位置精度因子:");
//天线海拔高度
subStr[9].Insert(strlen(subStr[9]),subStr[10]);
subStr[9].Insert(0," 天线海拔高度:");
//海平面分离度
subStr[11].Insert(strlen(subStr[11]),subStr[12]);
subStr[11].Insert(0," 海平面分离度:");
subStr[0] += subStr[1];
subStr[0] += subStr[2];
subStr[0] += subStr[4];
subStr[0] += GpsState;
subStr[0] += subStr[7];
subStr[0] += subStr[8];
subStr[0] += subStr[9];
subStr[0] += subStr[11];
//MessageBox(subStr[0]);
wFile.WriteString(subStr[0]);//将数据写入文件
}
//GPZDA数据
else if (subStr[0] == "$GPZDA")
{
//提取时间
subStr[1].Insert(2,':');
subStr[1].Insert(5,':');
subStr[1].Insert(0," UTC时间:");
//提取日期
subStr[2].Insert(strlen(subStr[2]),"日");
subStr[2].Insert(0,"月");
subStr[2].Insert(0,subStr[3]);
subStr[2].Insert(0,"年");
subStr[2].Insert(0,subStr[4]);
subStr[2].Insert(0,' ');
//当地时域描述
subStr[5].Insert(strlen(subStr[5]),"小时");
if (strlen(subStr[6]) > 3)
{
subStr[6] = subStr[6].Left(2);
}
else
{
subStr[6] = '0';
}
subStr[6] += "分";
subStr[6].Insert(0,subStr[5]);
subStr[6].Insert(0," 当地时域:");
subStr[0] += subStr[1];
subStr[0] += subStr[2];
subStr[0] += subStr[6];
//MessageBox(subStr[0]);
wFile.WriteString(subStr[0]);//将数据写入文件
}
//GPGSA数据
else if (subStr[0] == "$GPGSA")
{
//卫星捕获模式,以及定位模式
CString CatchLocation;
if (subStr[1] == 'M')
{
if (subStr[2] == '1')
{
CatchLocation = " 手动捕获卫星,未定位!";
}
else if (subStr[2] == '2')
{
CatchLocation = " 手动捕获卫星,2D定位!";
}
else if (subStr[2] == '3')
{
CatchLocation = " 手动捕获卫星,3D定位!";
}
}
else if (subStr[1] == 'A')
{
if (subStr[2] == '1')
{
CatchLocation =" 自动捕获卫星,未定位!";
}
else if (subStr[2] == '2')
{
CatchLocation =" 自动捕获卫星,2D定位!";
}
else if (subStr[2] == '3')
{
CatchLocation =" 自动捕获卫星,3D定位!";
}
}
//各卫星定位结果
subStr[3].Insert(0," 各卫星定位结果:");
subStr[3] += ' ';
subStr[4].Insert(0,subStr[3]);
subStr[4] += ' ';
subStr[5].Insert(0,subStr[4]);
subStr[5] += ' ';
subStr[6].Insert(0,subStr[5]);
subStr[6] += ' ';
subStr[7].Insert(0,subStr[6]);
subStr[7] += ' ';
subStr[8].Insert(0,subStr[7]);
subStr[8] += ' ';
subStr[9].Insert(0,subStr[8]);
subStr[9] += ' ';
subStr[10].Insert(0,subStr[9]);
subStr[10] += ' ';
subStr[11].Insert(0,subStr[10]);
subStr[11] += ' ';
subStr[12].Insert(0,subStr[11]);
subStr[12] += ' ';
subStr[13].Insert(0,subStr[12]);
subStr[13] += ' ';
subStr[14].Insert(0,subStr[13]);
subStr[14] += ' ';
//空间(三维)位置精度因子
subStr[15].Insert(0," 空间(三维)位置精度因子:");
//平面位置精度因子
subStr[16].Insert(0," 平面位置精度因子:");
//高度位置精度因子
subStr[17] = subStr[17].Left(3);
subStr[17].Insert(0," 高度位置精度因子:");
subStr[0] += CatchLocation;
subStr[0] += subStr[14];
subStr[0] += subStr[15];
subStr[0] += subStr[16];
subStr[0] += subStr[17];
/MessageBox(subStr[0]);
wFile.WriteString(subStr[0]);//将数据写入文件
}
//GPGSV数据
else if (subStr[0] == "$GPGSV")
{
///MessageBox(subStr[0]);
//卫星编号、卫星仰角(0~90度)、卫星方位角(0~359度)、信噪比
subStr[4].Insert(0,"卫星编号:");
subStr[5].Insert(0," 仰角:");
subStr[6].Insert(0," 方位角:");
subStr[7].Insert(0," 信噪比:");
subStr[4] += subStr[5];
subStr[4] += subStr[6];
subStr[4] += subStr[7];
///MessageBox(subStr[4]);
subStr[8].Insert(0,"卫星编号:");
subStr[9].Insert(0," 仰角:");
subStr[10].Insert(0," 方位角:");
subStr[11].Insert(0," 信噪比:");
subStr[8] += subStr[9];
subStr[8] += subStr[10];
subStr[8] += subStr[11];
MessageBox(subStr[8]);
subStr[12].Insert(0,"卫星编号:");
subStr[13].Insert(0," 仰角:");
subStr[14].Insert(0," 方位角:");
subStr[15].Insert(0," 信噪比:");
subStr[12] += subStr[13];
subStr[12] += subStr[14];
subStr[12] += subStr[15];
/MessageBox(subStr[12]);
subStr[16].Insert(0,"卫星编号:");
subStr[17].Insert(0," 仰角:");
subStr[18].Insert(0," 方位角:");
if (strlen(subStr[19]) > 3)
{
subStr[19] = subStr[19].Left(2);
}
else
{
subStr[19] = '0';
}
subStr[19].Insert(0," 信噪比:");
subStr[16] += subStr[17];
subStr[16] += subStr[18];
subStr[16] += subStr[19];
/MessageBox(subStr[16]);
wFile.WriteString(subStr[16]);//将数据写入文件
}
return str;
}
//读取文件数据并解析
void CGpsDataView::OnFileRead()
{
// TODO: 在此添加命令处理程序代码
CStdioFile myFile;
CString oneLine;
char cFlag = ',';
CString subStr[20];
//读取GPS数据文件
if(!myFile.Open(("gps.txt"),CFile::modeRead | CFile::typeText))
{
AfxMessageBox(_T("打开文件错误!"));
return;
}
else
{
/*do nothing*/
}
while (myFile.ReadString(oneLine))//读一行
{
//MessageBox(oneLine);
int j = GetSubStrCount(oneLine,cFlag); //得到该行的子字符串个数
//校验
if(CheckNum(oneLine))
{
MessageBox(_T("数据校验...接收正确!..."));
for (int i=0;i
{
subStr[i] = GetSubStr(oneLine,i,cFlag);
//MessageBox(subStr[i]);
}
Analyzing(oneLine); //解析
}
else
{
AfxMessageBox(_T("数据校验..接收错误!..."));
}
}
myFile.Close();
}
//***********************************************************************************************
//坐标转换
//度分秒--弧度
double Dms2Rad(double Dms)
{
double Degree, Miniute;
double Second;
int Sign;
double Rad;
if(Dms >= 0)
{
Sign = 1;
}
else
{
Sign = -1;
}
Dms = fabs(Dms); //绝对值
Degree = floor(Dms); // 取度 floor(2.800) = 2.0000
Miniute = floor(fmod(Dms * 100.0, 100.0)); //fmod 计算余数
Second = fmod(Dms * 10000.0, 100.0);
Rad = Sign * (Degree + Miniute / 60.0 + Second / 3600.0) * PI / 180.0;
return Rad;
}
double Rad2Dms(double Rad)
{
double Degree, Miniute;
double Second;
int Sign;
double Dms;
if(Rad >= 0)
{
Sign = 1;
}
else
{
Sign = -1;
}
Rad = fabs(Rad * 180.0 / PI);
Degree = floor(Rad);
Miniute = floor(fmod(Rad * 60.0, 60.0));
Second = fmod(Rad * 3600.0, 60.0);
Dms = Sign * (Degree + Miniute / 100.0 + Second / 10000.0);
return Dms;
}
//正算公式
bool GpsPoint::BL2xy()
{
//大地测量学基础 (吕志平 乔书波 北京:测绘出版社 2010.03)
double X; //由赤道至纬度为B的子午线弧长 (P106 5-41)
double N; //椭球的卯酉圈曲率半径
double t;
double t2;
double m;
double m2;
double ng2;
double cosB;
double sinB;
X = A1 * B * 180.0 / PI + A2 * sin(2 * B)
+ A3 * sin(4 * B) + A4 * sin(6 * B);
sinB = sin(B);
cosB = cos(B);
t = tan(B);
t2 = t * t;
N = a /sqrt(1 - e2 * sinB * sinB);
m = cosB * (L - L0);
m2 = m * m;
ng2 = cosB * cosB * e2 / (1 - e2);
//P156 (6-63公式)
x = X + N * t *(( 0.5 + ( (5 - t2 + 9 * ng2 + 4 * ng2 * ng2)
/ 24.0 + (61 - 58 * t2 + t2 * t2) * m2 / 720.0) * m2)* m2);
y = N * m * ( 1 + m2 * ( (1 - t2 + ng2) / 6.0 + m2 * ( 5 - 18 * t2 + t2 * t2
+ 14 * ng2 - 58 * ng2 * t2 ) / 120.0));
//y += 500000;
return true;
}
//反算公式
bool GpsPoint::xy2BL()
{
double sinB;
double cosB;
double t;
double t2;
double N; //椭球的卯酉圈曲率半径
double ng2;
double V;
double yN;
double preB0;
double B0;
double eta;
//y -= 500000;
B0 = x / A1;
do
{
preB0 = B0;
B0 = B0 * PI / 180.0;
B0 = (x - (A2 * sin(2 * B0) + A3 * sin(4 * B0) + A4 * sin(6 * B0))) / A1;
eta = fabs(B0 - preB0);
}while(eta > 0.000000001);
B0 = B0 * PI / 180.0;
B = Rad2Dms(B0);
sinB = sin(B0);
cosB = cos(B0);
t = tan(B0);
t2 = t * t;
N = a / sqrt(1 - e2 * sinB * sinB);
ng2 = cosB * cosB * e2 / (1 - e2);
V = sqrt(1 + ng2);
yN = y / N;
B = B0 - (yN * yN - (5 + 3 * t2 + ng2 - 9 * ng2 * t2) * yN * yN * yN * yN
/ 12.0 + (61 + 90 * t2 + 45 * t2 * t2) * yN * yN * yN * yN * yN * yN / 360.0)
* V * V * t / 2;
L = L0 + (yN - (1 + 2 * t2 + ng2) * yN * yN * yN / 6.0 + (5 + 28 * t2 + 24
* t2 * t2 + 6 * ng2 + 8 * ng2 * t2) * yN * yN * yN * yN * yN / 120.0) / cosB;
return true;
}
//设置中央子午线
bool GpsPoint::SetL0(double dL0)
{
L0 = Dms2Rad(dL0);
return true;
}
//将度分秒经纬度转换为弧度后再转换为平面坐标
bool GpsPoint::SetBL(double dB, double dL)
{
B = Dms2Rad(dB);
L = Dms2Rad(dL);
BL2xy();
return true;
}
bool GpsPoint::GetBL(double *dB, double *dL)
{
*dB = Rad2Dms(B);
*dL = Rad2Dms(L);
return true;
}
//将平面坐标转换为(弧度)经纬度
bool GpsPoint::Setxy(double dx, double dy)
{
x = dx;
y = dy;
xy2BL();
return true;
}
bool GpsPoint::Getxy(double *dx, double *dy)
{
*dx = x;
*dy = y;
return true;
}
GpsPoint_Krasovsky::GpsPoint_Krasovsky()
{
a = 6378245; //长半径
f = 298.3; //扁率的倒数 (扁率:(a-b)/a)
e2 = 1 - ((f - 1) / f) * ((f - 1) / f); //第一偏心率的平方
e12 = (f / (f - 1)) * (f / (f - 1)) - 1; //第二偏心率的平方
// 克拉索夫斯基椭球
A1 = 111134.8611;
A2 = -16036.4803;
A3 = 16.8281;
A4 = -0.0220;
}
//*************坐标转换
bool CGpsDataView::CoordCovert(CString latitude, CString longitude)
{
double bbb = atof(latitude);
double lll = atof(longitude);
//度分格式转换为度分秒格式
bbb = Dm2Dms(bbb);
lll = Dm2Dms(lll);
double MyL0 ; //中央子午线
double MyB = bbb ; //33 d 44 m 55.6666 s
double MyL = lll ; //3度带,109 d 22 m 33.4444 s
//计算当地中央子午线 ,3度带
MyL0 = fabs(MyL);
MyL0 = floor(MyL);
MyL0 = 3 * floor(MyL0 / 3 );
GpsPoint_Krasovsky MyPrj;
MyPrj.SetL0(MyL0);
MyPrj.SetBL(MyB, MyL);
double OutMyX;
double OutMyY;
OutMyX = MyPrj.x; //正算结果:坐标x
OutMyY = MyPrj.y; //结果:坐标y
CString strTemp1;
CString strTemp2;
CString strTemp3;
CString strTemp4;
strTemp1.Format("%f",OutMyX);
strTemp2.Format("%f",OutMyY);
strTemp1.Insert(0,"x = ");
strTemp2.Insert(0," , y = ");
strTemp2.Insert(0,strTemp1);
strTemp2.Insert(0," 坐标转换: ");
strTemp3.Format("%f12",MyB);
strTemp4.Format("%f12",MyL);
strTemp3.Insert(0,"B = ");
strTemp4.Insert(0," L = ");
strTemp4.Insert(0,strTemp3);
strTemp2.Insert(0,strTemp4);
//MessageBox(strTemp2);
DrawPoint(MyPrj.x,MyPrj.y);
return true;
}
//==================================
//度分格式转换为度分秒格式
double CGpsDataView::Dm2Dms(double Dm)
{
double Dms;
double temp;
temp = Dm - floor(Dm);
temp = (temp * 60) / 100;
Dm = floor(Dm);
Dm += temp;
Dm = Dm /100;
Dms = Dm;
return Dms;
}
//*************绘制线路 显示出路线
int count1=0;
bool bFirst = true;
double xTemp;
double yTemp;
void CGpsDataView::DrawPoint(double X, double Y)
{
Sleep(100);
//X = (X - floor(X))*100;
//Y = (Y - floor(Y))*100;
if (bFirst)
{
xTemp=X;
yTemp=Y;
bFirst=false;
}
CDC *pDC=GetDC();
CPen pen(PS_SOLID,3,RGB(255,20,20));
CPen *pOldPen;
CBrush *pOldBrush;
CBrush *pBrush=CBrush::FromHandle( (HBRUSH)GetStockObject(NULL_BRUSH) );
pOldPen=pDC->SelectObject(&pen);
pOldBrush=pDC->SelectObject(pBrush);
int a=(int)(100.0-(X-xTemp)*800.0);
int b=(int)(100.0+(Y-yTemp)*800.0);
//绘制点显示路径
pDC->Ellipse(a,b,a+5,b+5);
//计数
count1=count1+1;
pDC->SelectObject( pOldBrush );
pDC->SelectObject( pOldPen );
CString str;
str.Format("%.1f,%.1f,%d,%d,%d",X-xTemp,Y-yTemp,a,b,count1);
pDC->TextOut(10,10,str);
}