Subclassing QGestureRecognizer, trouble with calculating swipe angle
Asked Answered
L

0

0

I've subclassed QGestureRecognizer to detect QSwipeGesture. Problem is, QSwipeGesture::verticalDirection() and ::horizontalDirection() always return QSwipeGesture::Right and ::Up, never ::Left or ::Down.

The only real data of QSwipeGesture is swipeAngle so I must be calculating it wrong, could you help me?

This is my code:

static double translate_angle(double angle)
{
    return std::fmod(angle + 2*M_PI, 2*M_PI + 1e-12);
}

static double calcTheAngle(QPointF a, QPointF b)
{
    return translate_angle(qAtan2(b.y() - a.y(), b.x() - a.x()));
}

QGestureRecognizer::Result SwipeGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event)
{
    QMouseEvent * mouse = dynamic_cast<QMouseEvent*>(event);
    if (mouse != 0)
    {
        if (mouse->type() == QMouseEvent::MouseButtonPress)
        {
            auto* gesture = dynamic_cast<QSwipeGesture*>(state);
            if (gesture)
            {
                panning = true;
                startpoint = mouse->pos();
                gesture->setSwipeAngle(0.0);
                return TriggerGesture;
            }
        }
        if (panning && (mouse->type() == QMouseEvent::MouseMove))
        {
            auto* gesture = dynamic_cast<QSwipeGesture*>(state);
            if (gesture)
            {
                auto mpos = mouse->pos();
                float angle = calcTheAngle(startpoint, mpos);
                gesture->setSwipeAngle(angle);
                return TriggerGesture;
            }
        }
        if (mouse->type() == QMouseEvent::MouseButtonRelease)
        {
            auto* gesture = dynamic_cast<QSwipeGesture*>(state);
            if (gesture)
            {
                auto endpoint = mouse->pos();
                float angle = calcTheAngle(startpoint, endpoint);
                gesture->setSwipeAngle(angle);
                panning = false;
                if (startpoint == endpoint)
                {
                    return CancelGesture;
                }
                return FinishGesture;
            }
        }
        if (mouse->type() == QMouseEvent::MouseButtonDblClick)
        {
            panning = false;
            return CancelGesture;
        }
        return Ignore;
    }
    return Ignore;
}

And here I debug:

void GestureForm::swipeTriggered(QSwipeGesture *gesture)
{
    if (gesture->state() == Qt::GestureFinished) {
        auto h = gesture->horizontalDirection();
        auto v = gesture->verticalDirection();
        QMetaEnum metaEnum = QMetaEnum::fromType<QSwipeGesture::SwipeDirection>();
        auto msg = QString("swipeAngle: %1 (h: %2, v: %3)")
                       .arg(gesture->swipeAngle())
                       .arg(metaEnum.valueToKey(static_cast<int>(h)))
                       .arg(metaEnum.valueToKey(static_cast<int>(v)));
        qDebug() << qPrintable(msg);
        update();
    }
}

Now if I just swipe right, left, right, left and that's the output:

swipeAngle: 6.24993 (h: Right, v: Up)
swipeAngle: 3.15779 (h: Right, v: Up)
swipeAngle: 0.0223087 (h: Right, v: Up)
swipeAngle: 3.13778 (h: Right, v: Up)
swipeAngle: 6.28132 (h: Right, v: Up)
swipeAngle: 3.15987 (h: Right, v: Up)
swipeAngle: 0.0110901 (h: Right, v: Up)
swipeAngle: 3.17308 (h: Right, v: Up)
swipeAngle: 0.0259201 (h: Right, v: Up)
swipeAngle: 3.15913 (h: Right, v: Up)
swipeAngle: 0.0128198 (h: Right, v: Up)
swipeAngle: 3.09368 (h: Right, v: Up)
swipeAngle: 6.26643 (h: Right, v: Up)
swipeAngle: 3.12983 (h: Right, v: Up)
Lalita answered 13/8, 2023 at 16:13 Comment(3)
Seems to me that negative angles are not handled. Try setting the angle in [0, 2PI] range.Dasher
@Dasher thanks, I got rid of ::NoDirection, but now I have it always ::Right and ::Up. I updated the question, see the debug and translate_angle func on the top. But I feel like I'm two steps closer now thanks to both of you!Lalita
I see that Qt uses sexagesimal degrees: github.com/qt/qt/blob/0a2f2382541424726168804be2c90b91381608c6/…Tashia

© 2022 - 2025 — McMap. All rights reserved.