QT中Trackball的实现

Trackball,又叫轨迹球。其主要功能是用于将屏幕上的二维操作,转换到三维坐标系下的数据。
在这里插入图片描述
其主要是使用利用圆的方程,求出Z的位置。在这里插入图片描述


在QT的源码中,也发现Trackball 相关的代码,如下:
Qt5.6.0\Examples\Qt-5.6\qtbase\widgets\graphicsview\boxes\trackball.cpp

#include "trackball.h"
#include "scene.h"
#include <cmath>

//============================================================================//
//                                  TrackBall                                 //
//============================================================================//

TrackBall::TrackBall(TrackMode mode)
    : m_angularVelocity(0)
    , m_paused(false)
    , m_pressed(false)
    , m_mode(mode)
{
    m_axis = QVector3D(0, 1, 0);
    m_rotation = QQuaternion();
    m_lastTime = QTime::currentTime();
}

TrackBall::TrackBall(float angularVelocity, const QVector3D& axis, TrackMode mode)
    : m_axis(axis)
    , m_angularVelocity(angularVelocity)
    , m_paused(false)
    , m_pressed(false)
    , m_mode(mode)
{
    m_rotation = QQuaternion();
    m_lastTime = QTime::currentTime();
}

void TrackBall::push(const QPointF& p, const QQuaternion &)
{
    m_rotation = rotation();
    m_pressed = true;
    m_lastTime = QTime::currentTime();
    m_lastPos = p;
    m_angularVelocity = 0.0f;
}

void TrackBall::move(const QPointF& p, const QQuaternion &transformation)
{
    if (!m_pressed)
        return;

    QTime currentTime = QTime::currentTime();
    int msecs = m_lastTime.msecsTo(currentTime);
    if (msecs <= 20)
        return;

    switch (m_mode) {
    case Plane:
        {
            QLineF delta(m_lastPos, p);
            m_angularVelocity = 180*delta.length() / (PI*msecs);
            m_axis = QVector3D(-delta.dy(), delta.dx(), 0.0f).normalized();
            m_axis = transformation.rotatedVector(m_axis);
            m_rotation = QQuaternion::fromAxisAndAngle(m_axis, 180 / PI * delta.length()) * m_rotation;
        }
        break;
    case Sphere:
        {
            QVector3D lastPos3D = QVector3D(m_lastPos.x(), m_lastPos.y(), 0.0f);
            float sqrZ = 1 - QVector3D::dotProduct(lastPos3D, lastPos3D);
            if (sqrZ > 0)
                lastPos3D.setZ(std::sqrt(sqrZ));
            else
                lastPos3D.normalize();

            QVector3D currentPos3D = QVector3D(p.x(), p.y(), 0.0f);
            sqrZ = 1 - QVector3D::dotProduct(currentPos3D, currentPos3D);
            if (sqrZ > 0)
                currentPos3D.setZ(std::sqrt(sqrZ));
            else
                currentPos3D.normalize();

            m_axis = QVector3D::crossProduct(lastPos3D, currentPos3D);
            float angle = 180 / PI * std::asin(std::sqrt(QVector3D::dotProduct(m_axis, m_axis)));

            m_angularVelocity = angle / msecs;
            m_axis.normalize();
            m_axis = transformation.rotatedVector(m_axis);
            m_rotation = QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation;
        }
        break;
    }


    m_lastPos = p;
    m_lastTime = currentTime;
}

void TrackBall::release(const QPointF& p, const QQuaternion &transformation)
{
    // Calling move() caused the rotation to stop if the framerate was too low.
    move(p, transformation);
    m_pressed = false;
}

void TrackBall::start()
{
    m_lastTime = QTime::currentTime();
    m_paused = false;
}

void TrackBall::stop()
{
    m_rotation = rotation();
    m_paused = true;
}

QQuaternion TrackBall::rotation() const
{
    if (m_paused || m_pressed)
        return m_rotation;

    QTime currentTime = QTime::currentTime();
    float angle = m_angularVelocity * m_lastTime.msecsTo(currentTime);
    return QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:adb命令可以模拟简单的按键事件,当触摸屏不好使的时候就可以用咯。上篇有提到adb devices命令,就是用usb连接到手机或平板,这个时候就可以用adb shell 命令打开手机或平板终端了。输入input 回车有: 。 引用\[2\]:adb shell input命令使用说明 usage: input ... input text <string> input keyevent <key code number or name> input \[touchscreen|touchpad\] tap <x> <y> input \[touchscreen|touchpad\] swipe <x1> <y1> <x2> <y2> input trackball press input trackball roll <dx> <dy> 1. adb shell input text 。 引用\[3\]:模拟按键,可以是数字、符键或者是功能按键,keyevent后可以是按键的码值或者按键的名称,按键列表见文末的介绍,举例如下: //模拟按下数字0键 adb shell input keyevent "KEYCODE_0" //模拟按下返回键 adb shell input keyevent 4 3. adb shell input \[touchscreen|touchpad\] tap x y 。 问题:adb shell的input命令有哪些用法? 回答: 在adb shell,input命令有以下几种用法: 1. input text <string>: 模拟输入文本,可以输入任意字符串。 2. input keyevent <key code number or name>: 模拟按键事件,可以是按键的码值或者按键的名称。例如,模拟按下数字0键可以使用命令adb shell input keyevent "KEYCODE_0",模拟按下返回键可以使用命令adb shell input keyevent 4。 3. input \[touchscreen|touchpad\] tap <x> <y>: 模拟触摸屏幕上的点击事件,需要指定点击的坐标。例如,使用命令adb shell input touchscreen tap 100 200可以模拟在坐标(100, 200)处点击屏幕。 #### 引用[.reference_title] - *1* [adb shell input 命令](https://blog.csdn.net/yicao821/article/details/7327953)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [adb shell input命令使用说明](https://blog.csdn.net/qq_45477402/article/details/124659939)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值