GPS的NMEA数据转Google Earth的KML数据工具

本文介绍了将GPS的NMEA格式数据转换为Google Earth可读的KML数据的过程,以评估GPS定位精度。通过实现特定的代码转换,结合ASCII与UTF-8字符集处理,创建了一个QT界面工具,用户可以使用该工具生成KML文件并在Google Earth中查看轨迹。附带UI文件和可执行程序下载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值