/****************************************************************************** * QSkinny - Copyright (C) The authors * SPDX-License-Identifier: BSD-3-Clause *****************************************************************************/ #ifndef QSK_INTERVAL_H #define QSK_INTERVAL_H #include "QskGlobal.h" #include #include class QVariant; class QRectF; class QSK_EXPORT QskIntervalF { Q_GADGET Q_PROPERTY( qreal lowerBound READ lowerBound WRITE setLowerBound ) Q_PROPERTY( qreal upperBound READ upperBound WRITE setUpperBound ) Q_PROPERTY( qreal length READ length ) public: constexpr QskIntervalF() noexcept = default; constexpr QskIntervalF( qreal lowerBound, qreal upperBound ) noexcept; void setInterval( qreal lowerBound, qreal upperBound ) noexcept; constexpr bool operator==( const QskIntervalF& ) const noexcept; constexpr bool operator!=( const QskIntervalF& ) const noexcept; constexpr qreal lowerBound() const noexcept; void setLowerBound( qreal ) noexcept; constexpr qreal upperBound() const noexcept; void setUpperBound( qreal ) noexcept; constexpr qreal center() const noexcept; void spanFromLowerBound( qreal ) noexcept; void spanFromUpperBound( qreal ) noexcept; constexpr qreal length() const noexcept; void setLength( qreal ) noexcept; constexpr bool contains( qreal value ) const noexcept; constexpr bool contains( const QskIntervalF& ) const noexcept; constexpr bool isBoundary( qreal value ) const noexcept; bool fuzzyContains( qreal value ) const; bool fuzzyContains( const QskIntervalF& ) const; bool fuzzyIsBoundary( qreal value ) const; static constexpr QskIntervalF normalized( qreal value1, qreal value2 ) noexcept; void translate( qreal offset ) noexcept; constexpr QskIntervalF translated( qreal offset ) const noexcept; bool intersects( const QskIntervalF& ) const noexcept; QskIntervalF intersected( const QskIntervalF& ) const noexcept; void unite( const QskIntervalF& ) noexcept; QskIntervalF united( const QskIntervalF& ) const noexcept; void extend( qreal value ) noexcept; QskIntervalF extended( qreal value ) const noexcept; void stretch( qreal length ) noexcept; constexpr QskIntervalF stretched( qreal length ) const noexcept; QskIntervalF operator|( const QskIntervalF& ) const noexcept; QskIntervalF operator&( const QskIntervalF& ) const noexcept; QskIntervalF& operator|=( const QskIntervalF& ) noexcept; QskIntervalF& operator&=( const QskIntervalF& ) noexcept; QskIntervalF operator|( qreal ) const noexcept; QskIntervalF& operator|=( qreal ) noexcept; QskIntervalF fuzzyAligned( qreal stepSize ) const; constexpr bool isValid() const noexcept; constexpr bool isNull() const noexcept; constexpr bool isEmpty() const noexcept; void invalidate() noexcept; QskIntervalF interpolated( const QskIntervalF&, qreal progress ) const noexcept; static QRectF toRect( const QskIntervalF&, const QskIntervalF& ) noexcept; static QVariant interpolate( const QskIntervalF&, const QskIntervalF&, qreal progress ) noexcept; private: qreal m_lowerBound = 0.0; qreal m_upperBound = -1.0; }; Q_DECLARE_TYPEINFO( QskIntervalF, Q_MOVABLE_TYPE ); Q_DECLARE_METATYPE( QskIntervalF ) QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_INTEL(1572) inline constexpr QskIntervalF::QskIntervalF( qreal lowerBound, qreal upperBound ) noexcept : m_lowerBound( lowerBound ) , m_upperBound( upperBound ) { } inline void QskIntervalF::setInterval( qreal lowerBound, qreal upperBound ) noexcept { m_lowerBound = lowerBound; m_upperBound = upperBound; } inline void QskIntervalF::setLowerBound( qreal value ) noexcept { m_lowerBound = value; } inline void QskIntervalF::setUpperBound( qreal value ) noexcept { m_upperBound = value; } inline constexpr qreal QskIntervalF::lowerBound() const noexcept { return m_lowerBound; } inline constexpr qreal QskIntervalF::upperBound() const noexcept { return m_upperBound; } inline constexpr qreal QskIntervalF::center() const noexcept { return m_lowerBound + 0.5 * ( m_upperBound - m_lowerBound ); } inline constexpr qreal QskIntervalF::length() const noexcept { return ( m_upperBound > m_lowerBound ) ? ( m_upperBound - m_lowerBound ) : 0.0; } inline void QskIntervalF::setLength( qreal length ) noexcept { m_upperBound = m_lowerBound + length; } inline constexpr bool QskIntervalF::isValid() const noexcept { return m_lowerBound <= m_upperBound; } inline constexpr bool QskIntervalF::isNull() const noexcept { return m_lowerBound == m_upperBound; } inline constexpr bool QskIntervalF::isEmpty() const noexcept { return m_upperBound <= m_lowerBound; } inline void QskIntervalF::invalidate() noexcept { m_lowerBound = 0.0; m_upperBound = -1.0; } inline constexpr bool QskIntervalF::contains( qreal value ) const noexcept { return ( value >= m_lowerBound ) && ( value <= m_upperBound ); } inline constexpr bool QskIntervalF::contains( const QskIntervalF& interval ) const noexcept { return interval.isValid() && contains( interval.m_lowerBound ) && contains( interval.m_upperBound ); } inline constexpr bool QskIntervalF::isBoundary( qreal value ) const noexcept { return ( value == m_lowerBound ) || ( value == m_upperBound ); } inline void QskIntervalF::translate( qreal offset ) noexcept { m_lowerBound += offset; m_upperBound += offset; } inline constexpr QskIntervalF QskIntervalF::translated( qreal offset ) const noexcept { return QskIntervalF( m_lowerBound + offset, m_upperBound + offset ); } inline constexpr QskIntervalF QskIntervalF::normalized( qreal value1, qreal value2 ) noexcept { return ( value1 < value2 ) ? QskIntervalF( value1, value2 ) : QskIntervalF( value2, value1 ); } inline void QskIntervalF::stretch( qreal length ) noexcept { m_lowerBound = center() - 0.5 * length; m_upperBound = m_lowerBound + length; } inline constexpr QskIntervalF QskIntervalF::stretched( qreal length ) const noexcept { const auto lowerBound = center() - 0.5 * length; return QskIntervalF( lowerBound, lowerBound + length ); } inline QskIntervalF QskIntervalF::operator&( const QskIntervalF& other ) const noexcept { return intersected( other ); } inline QskIntervalF QskIntervalF::operator|( const QskIntervalF& other ) const noexcept { return united( other ); } inline QskIntervalF& QskIntervalF::operator|=( const QskIntervalF& other ) noexcept { unite( other ); return *this; } inline QskIntervalF& QskIntervalF::operator&=( const QskIntervalF& other ) noexcept { *this = intersected( other ); return *this; } inline constexpr bool QskIntervalF::operator==( const QskIntervalF& other ) const noexcept { return qFuzzyCompare( m_lowerBound, other.m_lowerBound ) && qFuzzyCompare( m_upperBound, other.m_upperBound ); } inline constexpr bool QskIntervalF::operator!=( const QskIntervalF& other ) const noexcept { return ( !( *this == other ) ); } inline QskIntervalF QskIntervalF::operator|( qreal value ) const noexcept { return extended( value ); } inline QskIntervalF& QskIntervalF::operator|=( qreal value ) noexcept { *this = *this | value; return *this; } QT_WARNING_POP #ifndef QT_NO_DEBUG_STREAM class QDebug; QSK_EXPORT QDebug operator<<( QDebug, const QskIntervalF& ); #endif #endif