⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gpssimdoc.cpp

📁 GPS信号模拟器源代码
💻 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 + -