## 一、前言说明
近期将这个模块彻底优化了下,最开始做的轨迹移动,是每次收到一个坐标点,就移动过去,这样显得很尴尬,跳跃式的前进,比如两个点之间距离很大,明显能看到直接跳过去的,虽然结果一样,但是看起来总是很不舒服,于是后面换了一种方案,那就是地图厂家提供的轨迹类,比如百度地图是BMapLib.LuShu,天地图是T.CarTrack,高德地图是marker本身的move动画,用起来都挺方便,效果也都还可以,确实是平滑移动的,而且还可以控制速度,那么问题来了,都是只能提前设置好经纬度坐标数据集合,启动后才是根据计算好的路径来运动,这个用来做轨迹回放,效果一级棒,但是实时轨迹肯定不行了,因为实时轨迹是每次都添加一个点,并不能提前知道所有点的集合,那怎办?
总归是有办法的,其实无论是BMapLib.LuShu还是T.CarTrack,都是js代码里面实现的计算两个点之间距离,然后主动生成多个点,比如两个经纬度坐标之间,线性插值法生成了几十个经纬度坐标,这些点连起来和两个点连起来的直线是一样的效果,然后开启了定时器,每次移动一个点即可,这样相当于全部的路径都均等分了,所以移动起来效果就是平滑的,既然js有这样的算法,那c++肯定也是可以的,于是先AI了一下,果真非常简单,就几行代码即可,传入两个经纬度坐标,给定需要生成多少个点,然后返回生成好的点集合,马上验证,效果又是一级棒。而且由于不依赖地图厂家的js,只需要基础的绘制线条和移动标注点,所以很容易支持所有地图厂家,根本不需要引入额外的js库。
## 二、效果图
## 三、相关代码
```cpp
#include "frmmapgpslive.h"
#include "ui_frmmapgpslive.h"
#include "qthelper.h"
#include "webview.h"
#include "maphelper.h"
#include "maputil.h"
frmMapGpsLive::frmMapGpsLive(QWidget *parent) : QWidget(parent), ui(new Ui::frmMapGpsLive)
{
ui->setupUi(this);
this->initForm();
this->initConfig();
QMetaObject::invokeMethod(this, "loadMap", Qt::QueuedConnection);
}
frmMapGpsLive::~frmMapGpsLive()
{
timer->stop();
delete ui;
}
void frmMapGpsLive::initForm()
{
//设置右侧固定宽度
ui->frame->setFixedWidth(AppData::RightWidth - 50);
//实例化浏览器控件并加入到布局
mapObj = NULL;
webView = new WebView(this);
webView->setLayout(ui->gridLayout, "frmMapGpsLive");
connect(webView, SIGNAL(loadSuccess()), this, SLOT(loadData()));
//启动定时器模拟/每次取出一个数据作为轨迹发过去
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(moveDevice()));
}
void frmMapGpsLive::initConfig()
{
MapHelper::loadMapCore(ui->cboxMapCore, AppConfig::GpsLiveCore);
connect(ui->cboxMapCore, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
connect(ui->cboxMapCore, SIGNAL(currentIndexChanged(int)), this, SLOT(loadMap()));
ui->cboxMapLocal->setCurrentIndex(AppConfig::GpsLiveLocal ? 1 : 0);
connect(ui->cboxMapLocal, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
connect(ui->cboxMapLocal, SIGNAL(currentIndexChanged(int)), this, SLOT(loadMap()));
ui->cboxMapType->setCurrentIndex(AppConfig::GpsLiveType);
connect(ui->cboxMapType, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
connect(ui->cboxMapType, SIGNAL(currentIndexChanged(int)), this, SLOT(loadMap()));
ui->cboxSmooth->setCurrentIndex(AppConfig::GpsLiveSmooth ? 1 : 0);
connect(ui->cboxSmooth, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
connect(ui->cboxSmooth, SIGNAL(currentIndexChanged(int)), this, SLOT(loadMap()));
}
void frmMapGpsLive::saveConfig()
{
AppConfig::GpsLiveCore = ui->cboxMapCore->itemData(ui->cboxMapCore->currentIndex()).toInt();
AppConfig::GpsLiveLocal = (ui->cboxMapLocal->currentIndex() == 1);
AppConfig::GpsLiveType = ui->cboxMapType->currentIndex();
AppConfig::GpsLiveSmooth = (ui->cboxSmooth->currentIndex() == 1);
AppConfig::writeConfig();
}
void frmMapGpsLive::loadMap()
{
//根据不同地图内核实例化地图类
MapCore mapCore = (MapCore)ui->cboxMapCore->itemData(ui->cboxMapCore->currentIndex()).toInt();
int mapType = ui->cboxMapType->currentIndex();





