








地图的二次开发中,显示实时轨迹或者轨迹回放都是必备的功能,也是目前最流行的无人机系统中的核心功能,这个功能思考了很久,主要是考虑需要哪些接口,比如可设置标注点的图片、移动的速度、移动的间隔、数据轨迹的颜色、移动轨迹的颜色等,可以是传入轨迹点集合进行轨迹回放,也可以动态append添加新的点做实时轨迹显示,轨迹点必须是平滑移动,根据移动的速度自动生成中间的点,比如两个点之间距离是1000米,速度是100米每次,则需要在这两个点之间产生9个点进行均等分,定时器每次取出一个点移动过去,如果没有这个处理,则上一个点移动到下一个点,都是瞬间移动过去,理论上很难看,因为实际上很可能是慢慢的平滑移动过去的。
一般都会绘制一个实时的轨迹,为了突出接口丰富,方便用户使用,这里还增加函数可以动态设置数据轨迹以及实时轨迹线是否可见,不需要的时候可以设置不可见,每种轨迹都可以动态设置颜色和粗细,上述功能全部封装成了movemarker类,只需要new就可以用,有几条就new几个实例就行,多次反复测试,效果非常棒,不枉费这些天这么久才把这个类思考好。我写程序一般是写草稿设计好思考好,然后再写,持续迭代,这个习惯保持了快20年,廉颇老矣,哎,年轻真好。

#include "movemarker.h"
#include "maputil.h"
#include "overlayhelper.h"
MoveMarker::MoveMarker(MapWidget *mapWidget, const QString &flag, const QPixmap &pixmap, const QList<QPointF> &points, int speed, int interval, bool smooth, bool moveInCenter) : QObject(mapWidget)
{
//生成对应覆盖物的唯一标识
this->dataLineFlag = "dataLine_" + flag;
this->moveLineFlag = "moveLine_" + flag;
this->moveMarkerFlag = "moveMarker_" + flag;
this->mapWidget = mapWidget;
this->pixmap = pixmap;
this->speed = speed;
this->smooth = smooth;
this->moveInCenter = moveInCenter;
//约定第一个点是起始点/如果只有一个点则说明是动态添加数据生成轨迹/多个点则是历史轨迹回放
angle = 0;
home = QPointF(121.424362, 31.175942);
int count = points.count();
if (count > 0) {
home = points.first();
}
//多个数据则说明是轨迹回放/设置到可视区域/实时轨迹则设置起点作为中心点
if (count > 1) {
mapWidget->setAutoView(points);
angle = MapUtil::getAngle(points.at(0), points.at(1));
//传入速度也就是每次移动的距离/逐个取出点生成平滑的点
if (smooth) {
for (int i = 0; i < count - 1; ++i) {
this->points << MapUtil::getLinePoints(points.at(i), points.at(i + 1), speed);
}
} else {
this->points = points;
}
} else {
this->points = points;
mapWidget->setCenter(home.x(), home.y());
}
//添加数据轨迹线
mapWidget->addPolyline(dataLineFlag, points, QColor(255, 0, 0), 5);
//添加移动轨迹线
mapWidget->addPolyline(moveLineFlag, QList<QPointF>() << home, QColor(0, 0, 0), 3);
//添加移动标注点
marker = mapWidget->addMarker(moveMarkerFlag, home.x(), home.y(), QString(), pixmap, angle, 2);
//定时器移动标注点
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(move()));
timer->setInterval(interval);
}
MoveMarker::~MoveMarker()
{
//停止定时器
timer->stop();
this->points.clear();
//删除覆盖物
mapWidget->deleteOverlay(dataLineFlag);
mapWidget->deleteOverlay(moveLineFlag);
mapWidget->deleteOverlay(moveMarkerFlag);
}
void MoveMarker::start()
{
index = 0;
if (points.count() > 1) {
angle = MapUtil::getAngle(points.at(0), points.at(1));
}
timer->start();
this->move();
}
void MoveMarker::pause()
{
timer->stop();
}
void MoveMarker::next()
{
timer->start();
}
void MoveMarker::stop()
{
timer->stop();
this->reset();
}
void MoveMarker::append(qreal lng, qreal lat)
{
QPointF curPoint(lng, lat);
QPointF prePoint = points.last();
if (smooth) {
this->points << MapUtil::getLinePoints(prePoint, curPoint, speed);
} else {
this->points << curPoint;
}
//添加到数据轨迹
mapWidget->addPolylineData(dataLineFlag, curPoint.x(), curPoint.y());
}
void MoveMarker::setInterval(int interval)
{
timer->setInterval(interval);
}
void MoveMarker::setSmooth(bool smooth)
{
this->smooth = smooth;
}
void MoveMarker::setMoveInCenter(bool moveInCenter)
{
this->moveInCenter = moveInCenter;
}
void MoveMarker::setDataLineVisible(bool visible)
{
mapWidget->setOverlayVisible(dataLineFlag, visible);
}
void MoveMarker::setMoveLineVisible(bool visible)
{
mapWidget->setOverlayVisible(moveLineFlag, visible);
}
void MoveMarker::setDataLineColor(const QColor &color, int width)
{
mapWidget->updatePolyline(dataLineFlag, QList<QPointF>(), color, width);
}
void MoveMarker::setMoveLineColor(const QColor &color, int width)
{
mapWidget->updatePolyline(moveLineFlag, QList<QPointF>(), color, width);
}
void MoveMarker::setText(const QString &text, const QColor &textColor, int textAlign, int textOffset, const QString &fontName, int fontSize, const QColor &bgColor, int bgAlpha, const QColor &borderColor, int borderWidth)
{
OverlayHelper::updateText(marker, text, textColor, textAlign, textOffset, fontName, fontSize, bgColor, bgAlpha, borderColor, borderWidth);
}
void MoveMarker::move()
{
//每次索引递增
index++;
//到了末尾则重来
if (index >= points.count()) {
this->reset();
return;
}
//过滤重复的坐标
QPointF curPoint = points.at(index);
QPointF prePoint = points.at(index - 1);
if (prePoint == curPoint) {
this->move();
return;
}
//移动到新的位置/带旋转角度
int angle = MapUtil::getAngle(prePoint, curPoint);
//mapWidget->updateMarker(moveMarkerFlag, curPoint.x(), curPoint.y(), "", QPixmap(), angle);
mapWidget->addPolylineData(moveLineFlag, curPoint.x(), curPoint.y());
//最新点一直作为中心点
if (moveInCenter) {
mapWidget->setCenter(curPoint.x(), curPoint.y());
}
}
void MoveMarker::reset()
{
//复位索引
index = 0;
//移动到起始点
//mapWidget->updateMarker(moveMarkerFlag, home.x(), home.y(), QString(), QPixmap(), angle, 2);
//移动轨迹复位
mapWidget->setPolylineData(moveLineFlag, QList<QPointF>() << home);
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。