📄 gpssimdoc.cpp
字号:
// GPSSimDoc.cpp : implementation of the CGPSSimDoc class
//
#include "stdafx.h"
#include "GPSSim.h"
#include "GPSSimDoc.h"
#include "gpssimdoc.h"
#include "math.h"
#include "assert.h"
#include ".\gpssimdoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CGPSSimDoc
IMPLEMENT_DYNCREATE(CGPSSimDoc, CDocument)
BEGIN_MESSAGE_MAP(CGPSSimDoc, CDocument)
//{{AFX_MSG_MAP(CGPSSimDoc)
//}}AFX_MSG_MAP
ON_COMMAND(ID_SIGNAL_CONNECT, OnSignalConnect)
END_MESSAGE_MAP()
// 获取奇偶校验值
char Parity(char *str, int len)
{
assert(str != NULL);
assert(strlen(str) >= len);
char a = 0;
for (int i = 0; i < len; i++)
{
a ^= str[i];
}
return a;
}
struct KNGEOCOORD
{
long lLatitude;
long lLongitude;
};
int CalcSpherDistance(KNGEOCOORD &point1,KNGEOCOORD &point2)
{
const double DE2RA = 0.01745329252;
const double FLATTENING = 1.000000/298.257223563; // Earth flattening (WGS84)
const double ERAD = 6378.137;
double lat1 = DE2RA * point1.lLatitude / 28800;
double lon1 = -DE2RA * point1.lLongitude / 28800;
double lat2 = DE2RA * point2.lLatitude / 28800;
double lon2 = -DE2RA * point2.lLongitude / 28800;
double F = (lat1 + lat2) / 2.0;
double G = (lat1 - lat2) / 2.0;
double L = (lon1 - lon2) / 2.0;
double sing = sin(G);//sine(G);//
double cosl = cos(L);//cosine(L);//
double cosf = cos(F);//cosine(F);//
double sinl = sin(L);//sine(L);//
double sinf = sin(F);//sine(F);//
double cosg = cos(G);//cosine(G);//
double S = sing*sing*cosl*cosl + cosf*cosf*sinl*sinl;
double C = cosg*cosg*cosl*cosl + sinf*sinf*sinl*sinl;
double W = atan2(sqrt(S),sqrt(C));
double R = sqrt((S*C))/W;
double H1 = (3 * R - 1.0) / (2.0 * C);
double H2 = (3 * R + 1.0) / (2.0 * S);
double D = 2 * W * ERAD;
return (int)(1.0 * 1000 * D * (1 + FLATTENING * H1 * sinf*sinf*cosg*cosg -
FLATTENING*H2*cosf*cosf*sing*sing));
}
bool CGPSSimDoc::m_bDisplayFlag = false;
/////////////////////////////////////////////////////////////////////////////
// CGPSSimDoc construction/destruction
CGPSSimDoc::CGPSSimDoc() : m_strPort("COM3")
{
m_cAccelerate = 1;
m_cAbnormal = 1;
m_cNosignal = 1;
//m_strPathName = "COM3";
m_dwBand = 9600;
m_lStatus = 0;
#ifdef _DEBUG
m_streamTrace.open("Trace.txt");
#endif
}
CGPSSimDoc::~CGPSSimDoc()
{
Reset();
m_serialPort.Close();
m_parse.Close();
CGPSSimApp *pApp = static_cast<CGPSSimApp*>(AfxGetApp());
pApp->WriteProfileInt("SerialPort", "Band", m_dwBand);
pApp->WriteProfileString("SerialPort", "COM", (LPCTSTR)m_strPort);
}
BOOL CGPSSimDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CGPSSimDoc serialization
void CGPSSimDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
}
else
{
}
}
/////////////////////////////////////////////////////////////////////////////
// CGPSSimDoc diagnostics
#ifdef _DEBUG
void CGPSSimDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CGPSSimDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
BOOL CGPSSimDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
//if (!CDocument::OnOpenDocument(lpszPathName))
// return FALSE;
m_parse.Open(lpszPathName);
Reset();
//srand(time(NULL));
return true;
}
// 获取下一的信号
int CGPSSimDoc::NextSegmant(vector<char*> &str)
{
char buff[1024];
if (!m_parse.Validate()) return -1;
if (m_parse.NextGGA(buff, sizeof(buff)) != 0) return -1;
m_textRawCur.clear();
char *tmp = new char[strlen(buff)+1];
strcpy(tmp, buff);
str.push_back(tmp);
while(1)
{
if (m_parse.NextLine(buff, sizeof(buff)) == -1) break;
if (buff[3] == 'G' && buff[4] == 'G' && buff[5] == 'A')
// if (buff[3] == 'R' && buff[4] == 'M' && buff[5] == 'C')
{
m_parse.Seek(-strlen(buff), ios_base::cur);
break;
}
tmp = new char[strlen(buff)+1];
strcpy(tmp, buff);
str.push_back(tmp);
}
return 0;
}
// 根据文字获得位置
int CGPSSimDoc::GetPos(const vector<char*> &str, KNPosition &pos)
{
vector<char*>::const_iterator it;
for (it = str.begin(); it != str.end(); ++it)
{
const char *cc = *it;
if (cc[3] == 'G' && cc[4] == 'G' && cc[5] == 'A')
{
GPGGA gga;
m_parse.ParseGGA(cc, gga);
char tmp[4];
memcpy (tmp, gga.longitude, 3);
tmp[3] = 0;
double dd = atof(tmp);
double mm = atof(&gga.longitude[3]);
pos.longitude = dd * 3600 * 8 + mm * 60 * 8;
memcpy (tmp, gga.latitude, 2);
tmp[2] = 0;
dd = atof(tmp);
mm = atof(&gga.latitude[2]);
pos.latitude = dd * 3600 * 8 + mm * 60 * 8;
pos.height = atof(gga.heighta);
strcpy(pos.time, gga.time);
}
else if (cc[3] == 'R' && cc[4] == 'M' && cc[5] == 'C')
{
GPRMC rmc;
m_parse.ParseRMC(cc, rmc);
pos.speed = atof(rmc.speed);
pos.direction = atof(rmc.dir);
strcpy(pos.data, rmc.date);
}
else if (cc[3] == 'V' && cc[4] == 'T' && cc[5] == 'G')
{
GPVTG vtg;
m_parse.ParseVTG(cc, vtg);
pos.speed = atof(vtg.speed);
pos.direction = atof(vtg.crsn);
pos.data[0] = 0;
}
}
return 0;
}
char temp[256] = {0};
int CGPSSimDoc::Next()
{
vector<char*>::const_iterator it;
if (m_lStatus & 0x02)
{
m_serialPort.Write(temp, strlen(temp));
}
/// 一个变换后的点相当于m_cAccelerate个原始点
for (int i = 0; i < 1/*m_cAccelerate*/; i++)
{
if (NextSegmant(m_textRawCur) == -1) return -1;
for (it = m_textRawCur.begin(); it != m_textRawCur.end() - 1; ++it)
{
m_textRawAll.push_back(*it);
if (m_lStatus & 0x02)
{
m_serialPort.Write(*it, strlen(*it));
}
}
m_textRawAll.push_back(*it);
int len = strlen(*it);
int k;
for( k = 0;k < 8; k++)
{
temp[k] = (*it)[len - 8 + k];
(*it)[len - 8 + k] = 0;
}
temp[k] = 0;
if (m_lStatus & 0x02)
{
m_serialPort.Write(*it, strlen(*it));
}
KNPosition pos;
GetPos(m_textRawCur, pos);
m_posRawAll.push_back(pos);
}
#if(0)
//=========================================================================
KNPosition pos;
// 随机加入异常点
int num = rand();
bool bModify = num < (RAND_MAX * m_cAbnormal / 100);
GetPos(m_textRawCur, pos);
pos.latitude += 4 * (rand() - RAND_MAX/2) / RAND_MAX;
pos.longitude += 4 * (rand() - RAND_MAX/2) / RAND_MAX;
if (!m_textTrnCur.empty())
{
float fdir = 0.0f;
float fspeed = 0.0f;
KNPosition pos2;
GetPos(m_textTrnCur, pos2);
KNGEOCOORD crd2 = {pos2.longitude, pos2.latitude};
KNGEOCOORD crd1 = {pos.longitude, pos.latitude};
pos.speed = CalcSpherDistance(crd2, crd1) * 36 / (m_cAccelerate*10);
if (pos2.latitude - pos.latitude)
fdir = (pos2.longitude - pos.longitude) / (pos2.latitude - pos.latitude);
else
fdir = 0;
pos.direction = atan(fdir) * 180 / 3.14159265f;
if (pos.direction < 0) pos.direction += 360;
}
// 处理后的数值
char date[20] = {0};
char time[20] = {0};
char lngitude[20] = {0};
char latitude[20] = {0};
char kmh[20] = {0}; // km/h
char kts[20] = {0}; // knots/s
char dir[8] = {0};
SYSTEMTIME st;
GetLocalTime(&st);
sprintf(date, "%02d%02d%04d", st.wDay, st.wMonth, st.wYear);
sprintf(time, "%02d%02d%02d.000",st.wHour,st.wMinute,st.wSecond);
date[4] = date[6];
date[5] = date[7];
date[6] = 0;
char dd[4];
char mm[8];
long ss = pos.longitude >> 3;
long ld = ss/3600;
float fm = float(ss % 3600) / 60.0f;
sprintf(lngitude, "%03d%07.4f", ld, fm);
ss = pos.latitude >> 3;
ld = ss / 3600;
fm = float(ss % 3600) / 60.0f;
sprintf(latitude, "%02d%07.4f", ld, fm);
float fkts = pos.speed/1.85185f;
sprintf(kmh, "%06.1f", pos.speed);
sprintf(kts, "%05.1f", pos.speed);
sprintf(dir, "%05.1f", pos.direction);
m_textTrnCur.clear();
for (it = m_textRawCur.begin(); it != m_textRawCur.end(); ++it)
{
char *cc = *it;
if (FALSE && cc[3] == 'G' && cc[4] == 'G' && cc[5] == 'A')
{
char *str = new char[strlen(cc)+1];
GPGGA gga;
m_parse.ParseGGA(cc, gga);
sprintf (
str,
"$GPGGA,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
time,
bModify?latitude:gga.latitude,
gga.ns,
bModify?lngitude:gga.longitude,
gga.ew,
gga.state,
gga.satellite,
gga.hdop,
gga.heighta,
gga.heightg,
gga.difftime,
gga.diffid);
char parity[8];
int cn = Parity(&str[1], strlen(str)-1);
sprintf(parity, "*%2x\r\n", cn);
strcat(str, parity);
m_textTrnCur.push_back(str);
m_textTrnAll.push_back(str);
}
else if (FALSE && cc[3] == 'R' && cc[4] == 'M' && cc[5] == 'C')
{
GPRMC rmc;
m_parse.ParseRMC(cc, rmc);
char *tmp = new char[strlen(cc)+1];
sprintf(
tmp,
"$GPRMC,%s,A,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
time,
bModify?latitude:rmc.latitude,
rmc.ns,
bModify?lngitude:rmc.longitude,
rmc.ew,
bModify?kmh:rmc.speed,
bModify?dir:rmc.dir,
date,
rmc.mag,
rmc.dir,
rmc.state);
char parity[8];
int cn = Parity(&tmp[1], strlen(tmp)-1);
sprintf(parity, "*%2x\r\n", cn);
strcat(tmp, parity);
m_textTrnCur.push_back(tmp);
m_textTrnAll.push_back(tmp);
}
else if (FALSE && cc[3] == 'V' && cc[4] == 'T' && cc[5] == 'G')
{
char *tmp = new char[strlen(cc)+1];
GPVTG vtg;
int ret = m_parse.ParseVTG(cc, vtg);
sprintf(
tmp,
"$GPVTG,%s,T,%s,M,,N,%s,K,%s",
bModify?dir:vtg.crsn,
vtg.crsm,
bModify?kts:vtg.kts,
bModify?kmh:vtg.speed,
vtg.mode);
char parity[6];
int cn = Parity(&tmp[1], strlen(tmp)-1);
sprintf(parity, "*%02x\r\n", i);
strcat(tmp, parity);
m_textTrnCur.push_back(tmp);
m_textTrnAll.push_back(tmp);
}
else
{
char *tmp = new char[strlen(cc)+1];
strcpy(tmp, cc);
m_textTrnCur.push_back(tmp);
m_textTrnAll.push_back(tmp);
}
}
GetPos(m_textTrnCur, pos);
m_posTrnAll.push_back(pos);
//-------------------------------------------------------------------------
// 发送数据
if (m_serialPort.IsOpen())
{
for (it = m_textTrnCur.begin(); it != m_textTrnCur.end(); ++it)
{
const char *str = *it;
m_serialPort.Write(str, strlen(str));
//TRACE(str);
}
}
#endif
return 0;
}
void CGPSSimDoc::Begin()
{
Reset();
}
bool CGPSSimDoc::Validate()
{
return m_parse.Validate();
}
BOOL CGPSSimDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
/*
ofstream ofs(lpszPathName);
vector<char*>::iterator it = m_textTrnAll.begin();
for (; it != m_textTrnAll.end(); ++it)
{
ofs << *it;
}
*/
return TRUE;
}
void CGPSSimDoc::OnSignalConnect()
{
if (m_lStatus & 0x01)
{
m_lStatus = 0x00;
m_serialPort.Close();
HMENU hMenu = GetMenu(AfxGetMainWnd()->m_hWnd);
HMENU hSubMenu = GetSubMenu(hMenu, 1);
ModifyMenu(hSubMenu,
ID_SIGNAL_CONNECT,
MF_BYCOMMAND|MF_STRING,
ID_SIGNAL_CONNECT,
"连接(&C)");
} // Close
else
{
m_lStatus = 0x00;
if (m_serialPort.Open(m_strPort, m_dwBand))
{
m_lStatus |= 0x01; // 成功打开端口
m_lStatus |= 0x02; // 需要发送数据
HMENU hMenu = GetMenu(AfxGetMainWnd()->m_hWnd);
HMENU hSubMenu = GetSubMenu(hMenu, 1);
ModifyMenu(hSubMenu,
ID_SIGNAL_CONNECT,
MF_BYCOMMAND|MF_STRING,
ID_SIGNAL_CONNECT,
"断开(&C)");
} // Succeed
else
{
//m_lStatus |= 0x00;// 打开失败
if (MessageBox(NULL, "打开串口失败!\n是否继续?", NULL, MB_YESNO|MB_ICONQUESTION)
== IDYES)
{
m_lStatus |= 0x02; // 打开失败, 但仍然继续.
}
} // Failed
} // Open
}
int CGPSSimDoc::Prior(void)
{
return 0;
}
int CGPSSimDoc::GetCount(void)
{
int count = 0;
while(NextSegmant(m_textRawCur) != -1) count++;
Reset();
return count;
}
int CGPSSimDoc::GetCurIndex(void)
{
return m_textRawCur.size();
}
void CGPSSimDoc::Reset(void)
{
m_parse.Reset();
vector<char*>::iterator it;
// all raw
it = m_textRawAll.begin();
for (; it != m_textRawAll.end(); ++it)
{
delete[] *it;
}
m_textRawAll.clear();
m_textRawCur.clear();
m_posRawAll.clear();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -