2020-05-02 11:57:58 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskIntervalF.h"
|
2020-07-31 07:40:04 +02:00
|
|
|
#include "QskFunctions.h"
|
2020-08-09 11:06:48 +02:00
|
|
|
|
|
|
|
#include <qvariant.h>
|
2020-05-02 11:57:58 +02:00
|
|
|
#include <algorithm>
|
|
|
|
|
2020-08-09 11:06:48 +02:00
|
|
|
static inline QskIntervalF qskInterpolated(
|
|
|
|
const QskIntervalF& intv1, const QskIntervalF& intv2, qreal progress )
|
|
|
|
{
|
|
|
|
const qreal lowerBound = intv1.lowerBound()
|
|
|
|
+ progress * ( intv2.lowerBound() - intv1.lowerBound() );
|
|
|
|
|
|
|
|
const qreal upperBound = intv1.upperBound()
|
|
|
|
+ progress * ( intv2.upperBound() - intv1.upperBound() );
|
|
|
|
|
|
|
|
return QskIntervalF( lowerBound, upperBound );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskIntervalF QskIntervalF::interpolated(
|
|
|
|
const QskIntervalF& to, qreal progress ) const noexcept
|
|
|
|
{
|
|
|
|
return qskInterpolated( *this, to, progress );
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant QskIntervalF::interpolate(
|
|
|
|
const QskIntervalF& intv1, const QskIntervalF& intv2, qreal progress ) noexcept
|
|
|
|
{
|
|
|
|
return QVariant::fromValue( qskInterpolated( intv1, intv2, progress ) );
|
|
|
|
}
|
|
|
|
|
2020-05-02 11:57:58 +02:00
|
|
|
void QskIntervalF::unite( const QskIntervalF& other ) noexcept
|
|
|
|
{
|
|
|
|
if ( isValid() )
|
|
|
|
{
|
|
|
|
if ( other.isValid() )
|
|
|
|
{
|
|
|
|
if ( other.m_lowerBound < m_lowerBound )
|
|
|
|
{
|
|
|
|
m_lowerBound = other.m_lowerBound;
|
|
|
|
}
|
|
|
|
else if ( other.m_upperBound > m_upperBound )
|
|
|
|
{
|
|
|
|
m_upperBound = other.m_upperBound;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( other.isValid() )
|
|
|
|
{
|
|
|
|
m_lowerBound = other.m_lowerBound;
|
|
|
|
m_upperBound = other.m_upperBound;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskIntervalF QskIntervalF::united( const QskIntervalF& other ) const noexcept
|
|
|
|
{
|
|
|
|
if ( isValid() )
|
|
|
|
{
|
|
|
|
if ( other.isValid() )
|
|
|
|
{
|
|
|
|
const auto min = std::min( m_lowerBound, other.m_lowerBound );
|
|
|
|
const auto max = std::max( m_upperBound, other.m_upperBound );
|
|
|
|
|
|
|
|
return QskIntervalF( min, max );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( other.isValid() )
|
|
|
|
return other;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
QskIntervalF QskIntervalF::intersected( const QskIntervalF& other ) const noexcept
|
|
|
|
{
|
|
|
|
if ( !isValid() )
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
if ( !other.isValid() )
|
|
|
|
return other;
|
|
|
|
|
|
|
|
if ( m_lowerBound <= other.m_lowerBound )
|
|
|
|
{
|
|
|
|
if ( m_upperBound < other.m_lowerBound )
|
|
|
|
return QskIntervalF();
|
|
|
|
|
|
|
|
const qreal max = std::min( m_upperBound, other.m_upperBound );
|
|
|
|
return QskIntervalF( other.m_lowerBound, max );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( other.m_upperBound < m_lowerBound )
|
|
|
|
return QskIntervalF();
|
|
|
|
|
|
|
|
const qreal max = std::min( m_upperBound, other.m_upperBound );
|
|
|
|
return QskIntervalF( m_lowerBound, max );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskIntervalF::intersects( const QskIntervalF& other ) const noexcept
|
|
|
|
{
|
|
|
|
if ( !isValid() || !other.isValid() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( m_lowerBound <= other.m_lowerBound )
|
|
|
|
return m_upperBound >= other.m_lowerBound;
|
|
|
|
else
|
|
|
|
return m_lowerBound <= other.m_upperBound;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskIntervalF::extend( qreal value ) noexcept
|
|
|
|
{
|
|
|
|
if ( !isValid() )
|
|
|
|
{
|
|
|
|
m_lowerBound = value;
|
|
|
|
m_upperBound = value;
|
|
|
|
}
|
|
|
|
else if ( value < m_lowerBound )
|
|
|
|
{
|
|
|
|
m_lowerBound = value;
|
|
|
|
}
|
|
|
|
else if ( value >= m_upperBound )
|
|
|
|
{
|
|
|
|
m_upperBound = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskIntervalF QskIntervalF::extended( qreal value ) const noexcept
|
|
|
|
{
|
|
|
|
if ( !isValid() )
|
|
|
|
return QskIntervalF( value, value );
|
|
|
|
|
|
|
|
const qreal lower = std::min( value, m_lowerBound );
|
|
|
|
const qreal upper = std::max( value, m_upperBound );
|
|
|
|
|
|
|
|
return QskIntervalF( lower, upper );
|
|
|
|
}
|
|
|
|
|
2020-07-31 07:40:04 +02:00
|
|
|
bool QskIntervalF::fuzzyContains( qreal value ) const
|
|
|
|
{
|
|
|
|
if ( !isValid() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( ( value < m_lowerBound ) && !qskFuzzyCompare( value, m_lowerBound ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( ( value > m_upperBound ) && !qskFuzzyCompare( value, m_upperBound ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-08-26 13:30:41 +02:00
|
|
|
bool QskIntervalF::fuzzyContains( const QskIntervalF& interval ) const
|
|
|
|
{
|
|
|
|
if ( !isValid() || !interval.isValid() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( ( interval.m_lowerBound < m_lowerBound )
|
|
|
|
&& !qskFuzzyCompare( interval.m_lowerBound, m_lowerBound ) )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ( interval.m_upperBound > m_upperBound )
|
|
|
|
&& !qskFuzzyCompare( interval.m_upperBound, m_upperBound ) )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-05-02 11:57:58 +02:00
|
|
|
#ifndef QT_NO_DEBUG_STREAM
|
|
|
|
|
|
|
|
#include <qdebug.h>
|
|
|
|
|
|
|
|
QDebug operator<<( QDebug debug, const QskIntervalF& interval )
|
|
|
|
{
|
|
|
|
debug.nospace() << "QskIntervalF("
|
|
|
|
<< interval.lowerBound() << "," << interval.upperBound() << ")";
|
|
|
|
|
|
|
|
return debug.space();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "moc_QskIntervalF.cpp"
|