• SkeyeGisMap地图扩展(四) 添加动态目标


    1、添加动态目标

    很多时候, 我们手中有一些数据, 它可以是人物/车辆/等等移动轨迹。

    现在我们想要实现一个动态移动的效果。

    同样的, 因为涉及到更改节点位置, 所以需要自定义一个事件:

    详细见: SkeyeGisMap 自定义事件

    class MoveEvent : public MapEvent
    {
    public:
        const static MapEvent::EventType MoveEventType = MapEvent::EventType::UserEvent + 1;
        MoveEvent(const QPointF &position, bool isClean) : MapEvent(MoveEventType), m_position(position), m_cleanTrack(isClean) { }
        QPointF m_position;
        bool m_cleanTrack = false;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    因为我们需要持续更新位置, 所有这里的事件携带了一个位置和是否清除轨迹的标志。

    接着, 我们使用 QVariantAnimation 模拟一个移动的效果。

    AddDynamicTarget()
    {
        setFlag(ItemIsFocusScope);
        setProcessFlags(ProcessFlag::UsePreLoadProcess | ProcessFlag::UseUserEvent);
        setFocus(true);
    
        m_animation = new QVariantAnimation(this);
        connect(m_animation, &QVariantAnimation::valueChanged, this, [this](const QVariant &value){
            pushEvent(new MoveEvent(value.toPointF(), false));
        });
    }
    
    virtual void preLoadProcess() override
    {
        auto assistant = rootMap()->assistant();
        auto startPosition = assistant->mapToDisplay(CoordinateReference::lonlatToWorld(QPointF(32.5810, 118.5970)));
        auto controlPosition1 = assistant->mapToDisplay(CoordinateReference::lonlatToWorld(QPointF(32.2133, 119.1839)));
        auto controlPosition2 = assistant->mapToDisplay(CoordinateReference::lonlatToWorld(QPointF(31.6718, 118.4196)));
        auto endPosition = assistant->mapToDisplay(CoordinateReference::lonlatToWorld(QPointF(31.2316, 118.9032)));
    
        m_busTrackNode = new MapLineNode(QVector<QPointF>{ startPosition }, 5, Qt::red);
        m_busNode = new MapImageNode(this, QImage(QQmlFile::urlToLocalFileOrQrc("qrc:/bus.png")), QPointF(startPosition), QSizeF(12000, 6000));
    
        auto lastLayer = rootMap()->lastLayer();
        if (lastLayer) {
            lastLayer->appendShape(m_busTrackNode);
            lastLayer->appendShape(m_busNode);
        }
    
        m_animation->setStartValue(startPosition);
        m_animation->setEndValue(endPosition);
        m_animation->setKeyValueAt(0.33, controlPosition1);
        m_animation->setKeyValueAt(0.66, controlPosition2);
        m_animation->setDuration(15000);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    这里用一张大巴的图片 MapImageNode 用作动态目标, 然后使用 MapLineNode 用作其轨迹。

    我们连接 QVariantAnimation::valueChanged 信号, 即动画值更新时推送一个移动事件。

    最后只需要处理该事件即可:

    virtual void processUserEvent(MapEvent *event) override
    {
        switch (event->type()) {
        case MoveEvent::MoveEventType:
        {
            auto moveEvent = static_cast<MoveEvent *>(event);
            if (moveEvent->m_cleanTrack) {
                m_busTrackNode->setPoints({});
            } else {
                auto position = m_busNode->position();
                auto targetPosition = moveEvent->m_position;
                QLineF line1(targetPosition, targetPosition - QPointF(0, 10));
                QLineF line2(position, targetPosition);
                m_busNode->setRotation(line2.angleTo(line1) - 90);
                m_busNode->setPosition(targetPosition);
                m_busTrackNode->appendPoint(targetPosition);
            }
        } break;
        default:
            break;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这里仅仅设置图片位置和添加轨迹点到线条中即可。

    然后我们还简单计算了一下方向, 将大巴旋转到正确的角度。

    为了清空轨迹和重置动画, 还增加了一个按键的事件 MapItem::keyPressEvent():

    virtual void keyPressEvent(QKeyEvent *ev) override
    {
        if (ev->key() == Qt::Key_Space) {
            if (m_animation->state() == QAbstractAnimation::Running)
                m_animation->stop();
            pushEvent(new MoveEvent(QPointF(), true));
            m_animation->start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2、效果展示

    在这里插入图片描述

    源码地址(dynamictarget): https://gitee.com/visual-opening/skeyegismap/tree/master/coremap/example

  • 相关阅读:
    2023年浙大MEM考前80天上岸经验分享
    【c++百日刷题计划】 ———— DAY14,奋战百天,带你熟练掌握基本算法
    Win32 简单日志实现
    列表变成向量 列表变向量 list vector
    在linux中安装pip
    混合灰狼和布谷鸟搜索优化算法(Matlab完整代码实现)
    ccd电池充电器坏了
    “机器学习”名字的由来
    用PHP组合数组,生成笛卡尔积的几个例子
    【MDP】①二次规划问题MATLAB求解器quadprog
  • 原文地址:https://blog.csdn.net/weixin_42113310/article/details/127675135