QT6 源,十章绘图(3):点 QPoint 与 QPointF 的源代码带注释

(1)本章开始学习 QT 里的绘图事件 QPaint。绘图涉及了画笔 QPen 与 QBrush。但绘图最终也涉及坐标系,与点,线,矩形这些基础的经典的图形定义。 所以,先来学习一下 QT 里如何为一个坐标系中的点定义一个类 , QPoint 与 QPointF。 本类的继承关系如下 :

在这里插入图片描述

(2)源码显示, 本类是支持流运算操作符的

在这里插入图片描述

(3) 不给这个全局模板友元函数举例,因为总是报错,我也不知道为什么,不可理解 :

在这里插入图片描述

++以及

在这里插入图片描述

(4)本类的源代码,都直接给出了 QT 自己的实现,就不再举例了,也因为时间紧迫。本类还是很容易根据源码进行理解的。举例的意义不大。重点还是画图, QPaint。 本 QPoint 类的源代码定义于 qpoint . h

#ifndef QPOINT_H
#define QPOINT_H

#include <QtCore/qnamespace.h>

#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGPoint;
#endif

QT_BEGIN_NAMESPACE


Q_CORE_EXPORT QDataStream & operator<< (QDataStream &, const QPoint & );
Q_CORE_EXPORT QDataStream & operator>> (QDataStream &,       QPoint & );
Q_CORE_EXPORT QDebug        operator<< (QDebug       , const QPoint & );

Q_CORE_EXPORT size_t qHash(QPoint key, size_t seed = 0) noexcept;

/*
The QPoint class defines a point in the plane using integer precision.

Note: All functions in this class are reentrant.

Detailed Description :
一个点由x坐标和y坐标指定,这些坐标可以通过x()和y()函数来访问。
如果x和y都被设置为0,则isNull()函数将返回true。
这些坐标可以通过setX()和setY()函数来设置(或修改),
或者通过rx()和ry()函数来设置,这些函数返回坐标的引用(从而允许直接操作)。

给定一个点p,以下陈述都是等价的:
    QPoint p;

    p.setX(p.x() + 1);
    p += QPoint(1, 0);
    p.rx()++;  //可见,引用更方便

QPoint对象也可以用作向量:加法和减法定义与向量相同(每个分量分别相加).
QPoint对象也可以被整数或qreal除或乘。

此外,QPoint类提供了manhattanLength()函数,  //曼哈顿距离
该函数提供了一个廉价的近似值,用于表示QPoint对象作为向量的长度。
最后,QPoint对象既可以被流式传输,也可以被比较。


*/


class QPoint
{
private:
    friend class QTransform;
    int xp;
    int yp;

    /*
    template <bool _Test, class _Ty = void>
    struct enable_if {}; // no member "type" when !_Test

    template <class _Ty>
    struct enable_if<true, _Ty> { // type is _Ty for _Test
        using type = _Ty;
    };

    template <bool _Test, class _Ty = void>
    using enable_if_t = typename enable_if<_Test, _Ty>::type;
    */
    template <std::size_t I,    typename P,  //这里期待 P 是 QPoint 相关的类型
             std::enable_if_t<(I < 2), bool> = true,
             std::enable_if_t<std::is_same_v<std::decay_t<P>, QPoint>, bool> = true>
    friend constexpr decltype(auto) get(P && p) noexcept //这里为本类定义了一个友元全局模板函数
    {                                        //不用在模板参数里给出 P,因为可以从函数形参里得到。
        if      constexpr (I == 0)
            return (std::forward<P>(p).xp);
        else if constexpr (I == 1)
            return (std::forward<P>(p).yp);
    }

public:
    constexpr QPoint() noexcept : xp(0), yp(0) {}

    constexpr QPoint(int xpos, int ypos) noexcept : xp(xpos), yp(ypos) {}

    constexpr inline bool    isNull() const noexcept { return xp == 0 && yp == 0; }
    constexpr inline int          x() const noexcept { return xp; }
    constexpr inline int          y() const noexcept { return yp; }
    constexpr inline int   &     rx()       noexcept { return xp; }
    constexpr inline int   &     ry()       noexcept { return yp; }
    constexpr inline void      setX(int x)  noexcept { xp = xpos; }
    constexpr inline void      setY(int y)  noexcept { yp = ypos; }

    constexpr inline int  manhattanLength() const    { return qAbs(x()) + qAbs(y()); }
    //注意,曼哈顿距离是坐标的 x + y,而不是 x^2 + y^2

    constexpr        QPoint   transposed() const noexcept { return {yp, xp}; } //坐标转置

    constexpr static inline int dotProduct(const QPoint & p1, const QPoint & p2)
    { return p1.xp * p2.xp + p1.yp * p2.yp; } //矢量乘法

    constexpr inline QPoint & operator+=(const QPoint & p     )
    {   xp += p.xp;
        yp += p.yp;
        return  * this;
    }
    constexpr inline QPoint & operator-=(const QPoint & p     )
    {   xp -= p.xp;
        yp -= p.yp;
        return  * this;
    }

    constexpr inline QPoint & operator*=(      float    factor)
    {   xp = qRound(xp * factor);
        yp = qRound(yp * factor);
        return  * this;
    }
    constexpr inline QPoint & operator*=(      double   factor)
    {   xp = qRound(xp * factor);
        yp = qRound(yp * factor);
        return  * this;
    }
    constexpr inline QPoint & operator*=(      int      factor)
    {   xp = xp * factor;
        yp = yp * factor;
        return  * this;
    }

    constexpr inline QPoint & operator/=(       qreal   divisor)
    {   xp = qRound(xp / divisor);
        yp = qRound(yp / divisor);
        return  * this;
    }

//*************************************************************************
//****************以下是关于本类的全局友元符号运算符函数*************************
//*************************************************************************

    friend constexpr inline    //点的相等比较
    bool   operator== (const QPoint & p1, const    QPoint & p2) noexcept
    { return p1.xp == p2.xp && p1.yp == p2.yp; }

    friend constexpr inline    //点的不等比较
    bool   operator!= (const QPoint & p1, const    QPoint & p2) noexcept
    { return p1.xp != p2.xp || p1.yp != p2.yp; }

    friend constexpr inline    //点的坐标相加
    QPoint operator+  (const QPoint & p1, const    QPoint & p2) noexcept
    { return QPoint(p1.xp + p2.xp, p1.yp + p2.yp); }

    friend constexpr inline    //点的坐标相减
    QPoint operator-  (const QPoint & p1, const    QPoint & p2) noexcept
    { return QPoint(p1.xp - p2.xp, p1.yp - p2.yp); }

    friend constexpr inline    //点的线性乘法
    QPoint operator*  (const QPoint & p ,           float   factor)
    { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }

    friend constexpr inline    //点的线性乘法
    QPoint operator*  (const QPoint & p,            double  factor)
    { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }

    friend constexpr inline    //点的线性乘法
    QPoint operator*  (const QPoint & p,            int      factor) noexcept
    { return QPoint(p.xp * factor, p.yp * factor); }

    friend constexpr inline    //点的线性乘法
    QPoint operator*  (      float    factor, const QPoint & p)
    { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }

    friend constexpr inline    //点的线性乘法
    QPoint operator*  (      double   factor, const QPoint & p)
    { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }

    friend constexpr inline    //点的线性乘法
    QPoint operator*  (      int      factor, const QPoint & p) noexcept
    { return QPoint(p.xp * factor, p.yp * factor); }

    friend constexpr inline   //点的线性除法
    QPoint operator/  (const QPoint & p, qreal c)
    { return QPoint(qRound(p.xp / c), qRound(p.yp / c)); }

    friend constexpr inline   //这不是加法, 这是正号, +8
    QPoint operator+  (const QPoint & p) noexcept { return p; }

    friend constexpr inline   //这不是减法, 这是负号, -8
    QPoint operator-  (const QPoint & p) noexcept
    { return QPoint(-p.xp, -p.yp); }


}; // 完结 class QPoint

Q_DECLARE_TYPEINFO(QPoint, Q_PRIMITIVE_TYPE);

QT_END_NAMESPACE

/*****************************************************************************
  QPoint/QPointF tuple protocol
 *****************************************************************************/

namespace std
{
    template <>
    class tuple_size<QT_PREPEND_NAMESPACE(QPoint)>
        : public integral_constant<size_t, 2> {};

    template <>
    class tuple_element<0, QT_PREPEND_NAMESPACE(QPoint)>
    { public: using type = int; };

    template <>
    class tuple_element<1, QT_PREPEND_NAMESPACE(QPoint)>
    { public: using type = int; };

    template <>
    class tuple_size<QT_PREPEND_NAMESPACE(QPointF)>
        : public integral_constant<size_t, 2> {};

    template <>
    class tuple_element<0, QT_PREPEND_NAMESPACE(QPointF)>
    { public: using type = QT_PREPEND_NAMESPACE(qreal); };

    template <>
    class tuple_element<1, QT_PREPEND_NAMESPACE(QPointF)>
    { public: using type = QT_PREPEND_NAMESPACE(qreal); };

}

#endif // QPOINT_H

(5) 给出浮点 QPointF 的源码,不再如同 QPoint 那样详细整理了

size_t qHash(QPointF, size_t seed = 0) = delete;
//QPointF stream functions
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPointF &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPointF &);
Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p);

class QPointF
{
private:
    friend class QTransform;

    qreal xp;
    qreal yp;

    template <std::size_t I,
             typename P,
             std::enable_if_t<(I < 2), bool> = true,
             std::enable_if_t<std::is_same_v<std::decay_t<P>, QPointF>, bool> = true>
    friend constexpr decltype(auto) get(P &&p) noexcept
    {
        if      constexpr (I == 0)
            return (std::forward<P>(p).xp);
        else if constexpr (I == 1)
            return (std::forward<P>(p).yp);
    }

public:
    constexpr QPointF() noexcept;
    constexpr QPointF(const QPoint & p) noexcept;
    constexpr QPointF(qreal xpos, qreal ypos) noexcept;

    inline           bool    isNull() const noexcept;
    constexpr inline qreal        x() const noexcept;
    constexpr inline qreal        y() const noexcept;
    constexpr inline qreal &     rx() noexcept;
    constexpr inline qreal &     ry() noexcept;
    constexpr inline void      setX(qreal x) noexcept;
    constexpr inline void      setY(qreal y) noexcept;

    constexpr inline qreal manhattanLength() const;
    constexpr QPointF transposed() const noexcept { return {yp, xp}; }

    constexpr QPoint  toPoint() const;

    constexpr inline QPointF & operator+=(const QPointF & p); //也有这些复合运算符成员函数

    constexpr inline QPointF & operator-=(const QPointF & p);

    constexpr inline QPointF & operator*=(      qreal     c);

    constexpr inline QPointF & operator/=(      qreal     c);

    constexpr static inline qreal dotProduct(const QPointF & p1, const QPointF & p2)
    {
        return p1.xp * p2.xp + p1.yp * p2.yp;
    }

    QT_WARNING_PUSH
    QT_WARNING_DISABLE_FLOAT_COMPARE
    friend constexpr inline bool operator==(const QPointF & p1, const QPointF & p2)
    {
        return ((!p1.xp || !p2.xp)
                ? qFuzzyIsNull(p1.xp - p2.xp)
                : qFuzzyCompare(p1.xp, p2.xp)) && (
                   (!p1.yp || !p2.yp)
                       ? qFuzzyIsNull(p1.yp - p2.yp)
                       : qFuzzyCompare(p1.yp, p2.yp)
                                                    );
    }

    friend constexpr inline bool operator!=(const QPointF & p1, const QPointF & p2)
    {
        return !(p1 == p2);
    }
    QT_WARNING_POP

    friend constexpr inline QPointF operator+(const QPointF & p1, const QPointF & p2)
    { return QPointF(p1.xp + p2.xp, p1.yp + p2.yp); }

    friend constexpr inline QPointF operator-(const QPointF & p1, const QPointF & p2)
    { return QPointF(p1.xp - p2.xp, p1.yp - p2.yp); }

    friend constexpr inline QPointF operator*(const QPointF & p , qreal c)
    { return QPointF(p.xp * c, p.yp * c); }

    friend constexpr inline QPointF operator*(qreal c, const QPointF & p)
    { return QPointF(p.xp * c, p.yp * c); }

    friend constexpr inline QPointF operator/(const QPointF & p , qreal divisor)
    {
        Q_ASSERT(divisor < 0 || divisor > 0);
        return QPointF(p.xp / divisor, p.yp / divisor);
    }

    friend constexpr inline QPointF operator+(const QPointF & p) { return p; }

    friend constexpr inline QPointF operator-(const QPointF & p)
    { return QPointF(-p.xp, -p.yp); }


}; //完结 class QPointF

Q_DECLARE_TYPEINFO(QPointF, Q_PRIMITIVE_TYPE);


/*****************************************************************************
  QPointF inline functions
 *****************************************************************************/

constexpr inline QPointF::QPointF() noexcept : xp(0), yp(0) { }

constexpr inline QPointF::QPointF(qreal xpos, qreal ypos) noexcept : xp(xpos), yp(ypos) { }

constexpr inline QPointF::QPointF(const QPoint &p) noexcept : xp(p.x()), yp(p.y()) { }

constexpr inline qreal QPointF::manhattanLength() const
{
    return qAbs(x()) + qAbs(y());
}

inline bool QPointF::isNull() const noexcept
{
    return qIsNull(xp) && qIsNull(yp);
}

constexpr inline qreal QPointF::x() const noexcept
{
    return xp;
}

constexpr inline qreal QPointF::y() const noexcept
{
    return yp;
}

constexpr inline void QPointF::setX(qreal xpos) noexcept
{
    xp = xpos;
}

constexpr inline void QPointF::setY(qreal ypos) noexcept
{
    yp = ypos;
}

constexpr inline qreal &QPointF::rx() noexcept
{
    return xp;
}

constexpr inline qreal &QPointF::ry() noexcept
{
    return yp;
}

constexpr inline QPointF &QPointF::operator+=(const QPointF &p)
{
    xp += p.xp;
    yp += p.yp;
    return *this;
}

constexpr inline QPointF &QPointF::operator-=(const QPointF &p)
{
    xp -= p.xp;
    yp -= p.yp;
    return *this;
}

constexpr inline QPointF &QPointF::operator*=(qreal c)
{
    xp *= c;
    yp *= c;
    return *this;
}

constexpr inline QPointF &QPointF::operator/=(qreal divisor)
{
    Q_ASSERT(divisor > 0 || divisor < 0);
    xp /= divisor;
    yp /= divisor;
    return *this;
}

constexpr inline QPoint QPointF::toPoint() const
{
    return QPoint(qRound(xp), qRound(yp));
}

(6)

谢谢

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值