1. 背景
在关于GPS定位的研究分析过程中,经常想要看在一段测试路径上,GPS的定位准确性如何,实际上,很自然的会想到把GPS数据显示在地图上,然而,并且,Google提供的Google Earth就是一个不错的工具,至于为什么不选择别的地图工具,是因为别的地图需要进行WGS84坐标系进行转换。
2. 实现代码
2.1 NMEA格式数据转化为KML的头文件
#ifndef CONVERT_H
#define CONVERT_H
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <memory.h>
#include <math.h>
#include <sstream>
#include <string.h>
using namespace std;
// 模块名称: convert
// Author: HSW
// Date: 2018-01-17
// 功能: 实现NMEA GGA数据分析
//
//
// NMEA GGA 数据分析
int splitString1(string lineBuf, vector<string>& subStrs, char dim = ',');
// ddmm.mmmm <==> dd.dddd
int fromDMToDegree(double ddmmPointMMMM, double& ddPointDDDD);
int fromDegreeToDM(double ddPointDDDD, double& ddmmPointMMMM);
// KML: 保存为KML文件
// strs: 分别包含: 描述
// 名称
// 经度
// 纬度
// 高度
int convertToKMLWithoutName(vector<string>& pointInfo, ofstream* pOfstr, int Mode);
#endif // CONVERT_H
#include "convert.h"
#include <windows.h>
#include <ctmstrconvert.h>
static wstring kml_S = L"<kml xmlns=\"http://earth.google.com/kml/2.0\">\r\n";
static wstring kmlFolder_S = L"<Folder>\r\n";
static wstring kmlPlacemark_S = L"<Placemark>";
static wstring kmlDescription_S = L"<description>";
static wstring kmlDescription_E = L"</description>";
static wstring kmlName_S = L"<name>";
static wstring kmlName_E = L"</name>";
static wstring kmlLookat_S = L"<LookAt>";
static wstring kmlLon_S = L"<longitude>";
static wstring kmlLon_E = L"</longitude>";
static wstring kmlLat_S = L"<latitude>";
static wstring kmlLat_E = L"</latitude>";
static wstring kmlRange_S = L"<range>";
static wstring kmlRange_E = L"</range>";
static wstring kmlTilt_S = L"<tilt>";
static wstring kmlTilt_E = L"</tilt>";
static wstring kmlHeading_S = L"<heading>";
static wstring kmlHeading_E = L"</heading>";
static wstring kmlLookat_E = L"</LookAt>";
static wstring kmlPoint_S = L"<Point>";
static wstring kmlCoordinates_S = L"<coordinates>";
static wstring kmlCoordinates_E = L"</coordinates>";
static wstring kmlPoint_E = L"</Point>";
static wstring kmlPlacemark_E = L"</Placemark>\r\n";
static wstring kmlFolder_E = L"</Folder>\r\n";
static wstring kml_E = L"</kml>\r\n";
static wstring kml_default_range = L"20000";
static wstring kml_default_tilt = L"0";
static wstring kml_default_heading = L"3";
static string kml_default_altitude = "0";
static wstring kml_default_pointSetName = L"Positions";
// 实现差分前后的数据处理
//
static char exampleGGA[4][128] = {"$GPGGA,062926.000,4538.7429,N,12639.4155,E,2,08,1.0,196.6,M,0.0,M,23,1544*6C",
"$GPGGA,062926.000,4538.7429,N,12639.4155,W,2,08,1.0,196.6,M,0.0,M,23,1544*6C",
"$GPGGA,062926.000,4538.7429,S,12639.4155,E,2,08,1.0,196.6,M,0.0,M,23,1544*6C",
"$GPGGA,062926.000,4538.7429,N,12639.4155,W,2,08,1.0,196.6,M,0.0,M,23,1544*6C"};
// 将std::string 转为 利用UTF-8编码的std::string
// step1: 将std::string 转为 std::wstring
// 方法1:
BOOL StringToWString(const std::string &str,std::wstring &wstr)
{
int nLen = (int)str.length();
wstr.resize(nLen,L' ');
int nResult = MultiByteToWideChar(CP_ACP,0,(LPCSTR)str.c_str(),nLen,(LPWSTR)wstr.c_str(),nLen);
if (nResult == 0)
{
return FALSE;
}
return TRUE;
}
//wstring高字节不为0,返回FALSE
BOOL WStringToString(const std::wstring &wstr,std::string &str)
{
int nLen = (int)wstr.length();
str.resize(nLen,' ');
int nResult = WideCharToMultiByte(CP_ACP,0,(LPCWSTR)wstr.c_str(),nLen,(LPSTR)str.c_str(),nLen,NULL,NULL);
if (nResult == 0)
{
return FALSE;
}
return TRUE;
}
std::string to_utf8(const wchar_t* buffer, int len)
{
int nChars = ::WideCharToMultiByte(
CP_UTF8,
0,
buffer,
len,
NULL,
0,
NULL,
NULL);
if (nChars == 0) return "";
string newbuffer;
newbuffer.resize(nChars) ;
::WideCharToMultiByte(
CP_UTF8,
0,
buffer,
len,
const_cast< char* >(newbuffer.c_str()),
nChars,
NULL,
NULL);
return newbuffer;
}
// std::string 转为 std::string UTF-8
std::string to_utf8(const std::wstring& str)
{
return to_utf8(str.c_str(), (int)str.size());
}
// NMEA GGA 数据分析
int splitString1(string lineBuf, vector<string>& subStrs, char dim)
{
size_t startPos = lineBuf.find('$');
size_t endPos = lineBuf.find('*');
int iter;
int count = 0;
char subStr[64] = {0};
int findGGA = 0;
if(startPos != string::npos && endPos != string::npos)
{
for(iter = startPos + 1; iter < endPos; ++iter)
{
char ch = lineBuf.at(iter);
if(ch == dim)
{
string tmp = string(subStr);
if(tmp.find("GGA") != string::npos)
{
findGGA = 1;
}
subStrs.push_back(string(subStr));
memset(subStr,0, sizeof(subStr));
count = 0;
}
else
{
subStr[count] = lineBuf.at(iter);
count++;
}
}
subStrs.push_back(string(subStr));
}
if(findGGA)
{
return 0;
}
else
{
return -1;
}
}
// DD.DDDD ==> ddmm.mmmm
int fromDegreeToDM(double ddPointDDDD, double& ddmmPointMMMM)
{
int tmpInt = (int)floor(ddPointDDDD);
double tmpFloat = ddPointDDDD - tmpInt;
ddmmPointMMMM = tmpInt * 100 + tmpFloat * 60;
return 0;
}
// ddmm.mmmm ==> DD.DDDD
int fromDMToDegree(double ddmmPointMMMM, double& ddPointDDDD)
{
int tmpInt = floor(ddmmPointMMMM / 100);
double tmpFloat = ddmmPointMMMM - tmpInt * 100;
ddPointDDDD = tmpInt + tmpFloat / 60;
return 0;
}
// nmea 计算检查和
unsigned char checkSum(const char* buf)
{
int isStart = 0;
int iter = 0;
unsigned char checksum = 0;
while(1)
{
if((unsigned char)buf[iter] == '$')
{
isStart = 1;
++iter;
continue;
}
if(isStart)
{
if((unsigned char)buf[iter] == '*')
{
break;
}
checksum ^= buf[iter];
}
++iter;
}
// cout << "checksum = " << checksum << endl;
return checksum;
}
// KML: 保存为KML文件, 不包含点的名称
// strs: 分别包含: 描述
// 经度
// 纬度
// 注意:坐标点的高度默认设置为0
int convertToKMLWithoutName(vector<string>& pointInfo, ofstream* pOfstr, int Mode)
{
wstring utf8wStr = L""; // 宽字符
string utf8Str = ""; // UTF-8字符串
if(Mode == 0)
{
utf8Str = to_utf8(kml_S);
// pOfstr->write(kml_S.c_str(), kml_S.length());
pOfstr->write(utf8Str.c_str(), utf8Str.length());
utf8Str.clear();
utf8Str = to_utf8(kmlFolder_S);
// pOfstr->write(kmlFolder_S.c_str(), kmlFolder_S.length());
pOfstr->write(utf8Str.c_str(), utf8Str.length());
utf8Str.clear();
// 名称: kml文件的名称
utf8Str = to_utf8(kmlName_S);
//pOfstr->write(kmlName_S.c_str(), kmlName_S.length());
pOfstr->write(utf8Str.c_str(), utf8Str.length());
utf8Str.clear();
StringToWString(pointInfo[0], utf8wStr);
utf8Str = to_utf8(utf8wStr);
//pOfstr->write(pointInfo[0].c_str(), pointInfo[0].length());
pOfstr->write(utf8Str.c_str(), utf8Str.length());
utf8Str.clear();
utf8wStr.clear();
utf8Str = to_utf8(kmlName_E);
// pOfstr->write(kmlName_E.c_str(), kmlName_E.length());
pOfstr->write(utf8Str.c_str(), utf8Str.length());
utf8Str.clear();
// 点集合名称: kml
// 点集合名称: kml
string outputPath = pointInfo[0];
size_t pos = outputPath.find_last_of('/');
if(pos != string::npos)
{
utf8Str = to_utf8(kmlName_S);
//pOfstr->write(kmlName_S.c_str(), kmlName_S.length());
pOfstr->write(utf8Str.c_str(), utf8Str.length());
utf8Str.clear();
// utf8Str = to_utf8(kml_default_pointSetName);
//pOfstr->write(kml_default_pointSetName.c_str(), kml_default_pointSetName.length());
CTMStrConvert converter;
wstring wPointsetName = converter.StringToWString(outputPath.substr(pos + 1, o