首页| 论坛| 消息
主题:不依赖任何AI代码/纯qpainter实现的航线规划/飞行轨迹规划和模拟/无人机轨迹
liudianwu发表于 2026-04-19 09:56
## 一、前言说明
在2026年的今天,能够不用AI,纯古法编程实现这个航线规划,还是有不小难度的,在地图组件的基础上开发,之前已经实现了超级标注点图形,加上折线图形的绘制,以及支持编辑状态拖曳调整,对于航线规划的基础功能都有了,现在就是还需要在折线线条上绘制一个箭头。以前web版本的航线规划,用了个取巧的方案,就是搞了个标注点显示在中间位置,对于箭头作为标注点的图片,然后标注点可以旋转,每次都计算上一个点和当前点之间的旋转角度,尽管widget开发的地图组件也可以按照这个思路去完成,想了很久还是决定直接用painter绘制更优,没必要再引人一个多余的标注点,毕竟一整个航线下来,标注点的数量成倍增加了,如果能直接在折线上根据两点坐标,计算出来并绘制箭头,好处实在太多了,其实那个箭头就是传入两个点,计算出中间点,然后两侧伸展两个点,最后三个点形成一个新的折线,绘制这个折线即可。
web版本的地图组件本身支持的最大标注点数量有限,测下来500个就已经是性能瓶颈了,明显的卡顿不及时,而widget版本的至少1W个起步都毫无压力,而且是瞬间完成,性能百倍提升一点不夸张。本人之前搞个自定义控件大全,在圈内有Qt控件祖师爷之称,所谓心中有坐标,万物皆painter。就是因为有这个擅长点,各种各样的绘制都不在话下。
## 二、效果图

## 三、相关代码
```cpp
#include "markermove.h"
#include "maputil.h"
#include "overlayhelper.h"
MarkerMove::MarkerMove(MapWidget *mapWidget, const QString &flag, const QPixmap &pixmap, const QVector &points, int speed, int interval, bool smooth, bool moveInCenter) : QObject(mapWidget)
{
//生成对应覆盖物的唯一标识
this->dataLineFlag = "dataLine_" + flag;
this->moveLineFlag = "moveLine_" + flag;
this->markerMoveFlag = "markerMove_" + 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 points = points;
}
} else {
this->points = points;
mapWidget->setCenter(home);
}
//添加数据轨迹线
mapWidget->addPolyline(dataLineFlag, points, QColor(255, 0, 0), 5);
//添加移动轨迹线
mapWidget->addPolyline(moveLineFlag, QVector() addMarker(markerMoveFlag, home, QString(), pixmap, angle, 2);
//定时器移动标注点
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(move()));
timer->setInterval(interval);
}
MarkerMove::~MarkerMove()
{
}
void MarkerMove::start()
{
index = 0;
if (points.count() > 1) {
angle = MapUtil::getAngle(points.at(0), points.at(1));
}
timer->start();
this->move();
emit moveStep(home);
}
void MarkerMove::pause()
{
timer->stop();
}
void MarkerMove::play()
{
timer->start();
}
void MarkerMove::stop()
{
timer->stop();
this->reset();
}
void MarkerMove::clear()
{
//停止定时器
timer->stop();
this->points.clear();
//删除轨迹线和标注点
OverlayHelper::redraw = false;
mapWidget->deleteOverlay(dataLineFlag);
mapWidget->deleteOverlay(moveLineFlag);
mapWidget->deleteOverlay(markerMoveFlag);
OverlayHelper::redraw = true;
}
void MarkerMove::append(const QPointF &point)
{
QPointF curPoint(point);
QPointF prePoint = points.last();
if (smooth) {
this->points points addPolylineData(dataLineFlag, curPoint);
}
void MarkerMove::setInterval(int interval)
{
timer->setInterval(interval);
}
void MarkerMove::setSmooth(bool smooth)
{
t

浏览大图
下一页 (1/3)
回帖(0):

全部回帖(0)»
最新回帖
收藏本帖
发新帖