- 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<i-1;j++)
- {
- iStart = str.Find(cFlag , iStart+1);
- }
- return str.Mid(iStart+1 , str.GetLength()-iStart-1);
- }
- else
- {
- //do nothing
- }
- for (; j<i; 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<j;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<j;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);
- }