QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskIntervalF.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskIntervalF.h"
7#include "QskFunctions.h"
8
9#include <qvariant.h>
10#include <qrect.h>
11#include <algorithm>
12
13static void qskRegisterIntervalF()
14{
15 qRegisterMetaType< QskIntervalF >();
16
17#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
18 QMetaType::registerEqualsComparator< QskIntervalF >();
19#endif
20}
21
22Q_CONSTRUCTOR_FUNCTION( qskRegisterIntervalF )
23
24static inline QskIntervalF qskInterpolated(
25 const QskIntervalF& intv1, const QskIntervalF& intv2, qreal progress )
26{
27 const qreal lowerBound = intv1.lowerBound()
28 + progress * ( intv2.lowerBound() - intv1.lowerBound() );
29
30 const qreal upperBound = intv1.upperBound()
31 + progress * ( intv2.upperBound() - intv1.upperBound() );
32
33 return QskIntervalF( lowerBound, upperBound );
34}
35
36QskIntervalF QskIntervalF::interpolated(
37 const QskIntervalF& to, qreal progress ) const noexcept
38{
39 return qskInterpolated( *this, to, progress );
40}
41
42QVariant QskIntervalF::interpolate(
43 const QskIntervalF& intv1, const QskIntervalF& intv2, qreal progress ) noexcept
44{
45 return QVariant::fromValue( qskInterpolated( intv1, intv2, progress ) );
46}
47
48void QskIntervalF::unite( const QskIntervalF& other ) noexcept
49{
50 if ( isValid() )
51 {
52 if ( other.isValid() )
53 {
54 if ( other.m_lowerBound < m_lowerBound )
55 {
56 m_lowerBound = other.m_lowerBound;
57 }
58 else if ( other.m_upperBound > m_upperBound )
59 {
60 m_upperBound = other.m_upperBound;
61 }
62 }
63 }
64 else
65 {
66 if ( other.isValid() )
67 {
68 m_lowerBound = other.m_lowerBound;
69 m_upperBound = other.m_upperBound;
70 }
71 }
72}
73
74QskIntervalF QskIntervalF::united( const QskIntervalF& other ) const noexcept
75{
76 if ( isValid() )
77 {
78 if ( other.isValid() )
79 {
80 const auto min = std::min( m_lowerBound, other.m_lowerBound );
81 const auto max = std::max( m_upperBound, other.m_upperBound );
82
83 return QskIntervalF( min, max );
84 }
85 }
86 else
87 {
88 if ( other.isValid() )
89 return other;
90 }
91
92 return *this;
93}
94
95QskIntervalF QskIntervalF::intersected( const QskIntervalF& other ) const noexcept
96{
97 if ( !isValid() )
98 return *this;
99
100 if ( !other.isValid() )
101 return other;
102
103 if ( m_lowerBound <= other.m_lowerBound )
104 {
105 if ( m_upperBound < other.m_lowerBound )
106 return QskIntervalF();
107
108 const qreal max = std::min( m_upperBound, other.m_upperBound );
109 return QskIntervalF( other.m_lowerBound, max );
110 }
111 else
112 {
113 if ( other.m_upperBound < m_lowerBound )
114 return QskIntervalF();
115
116 const qreal max = std::min( m_upperBound, other.m_upperBound );
117 return QskIntervalF( m_lowerBound, max );
118 }
119}
120
121bool QskIntervalF::intersects( const QskIntervalF& other ) const noexcept
122{
123 if ( !isValid() || !other.isValid() )
124 return false;
125
126 if ( m_lowerBound <= other.m_lowerBound )
127 return m_upperBound >= other.m_lowerBound;
128 else
129 return m_lowerBound <= other.m_upperBound;
130}
131
132void QskIntervalF::extend( qreal value ) noexcept
133{
134 if ( !isValid() )
135 {
136 m_lowerBound = value;
137 m_upperBound = value;
138 }
139 else if ( value < m_lowerBound )
140 {
141 m_lowerBound = value;
142 }
143 else if ( value >= m_upperBound )
144 {
145 m_upperBound = value;
146 }
147}
148
149QskIntervalF QskIntervalF::extended( qreal value ) const noexcept
150{
151 if ( !isValid() )
152 return QskIntervalF( value, value );
153
154 const qreal lower = std::min( value, m_lowerBound );
155 const qreal upper = std::max( value, m_upperBound );
156
157 return QskIntervalF( lower, upper );
158}
159
160void QskIntervalF::spanFromLowerBound( qreal value ) noexcept
161{
162 if ( !isValid() )
163 {
164 m_lowerBound = value;
165 m_upperBound = value;
166 }
167 else
168 {
169 m_lowerBound = value;
170 if ( m_lowerBound > m_upperBound )
171 m_upperBound = m_lowerBound;
172 }
173}
174
175void QskIntervalF::spanFromUpperBound( qreal value ) noexcept
176{
177 if ( !isValid() )
178 {
179 m_lowerBound = value;
180 m_upperBound = value;
181 }
182 else
183 {
184 m_upperBound = value;
185 if ( m_lowerBound > m_upperBound )
186 m_lowerBound = m_upperBound;
187 }
188}
189
190QskIntervalF QskIntervalF::fuzzyAligned( qreal stepSize ) const
191{
192 auto v1 = m_lowerBound;
193 auto v2 = m_upperBound;
194
195 const auto max = std::numeric_limits< qreal >::max();
196
197 if ( -max + stepSize <= v1 )
198 {
199 const auto v = qskFuzzyFloor( v1, stepSize );
200 if ( !qskFuzzyCompare( v1, v ) )
201 v1 = v;
202 }
203
204 if ( max - stepSize >= v2 )
205 {
206 const auto v = qskFuzzyCeil( v2, stepSize );
207 if ( !qskFuzzyCompare( v2, v ) )
208 v2 = v;
209 }
210
211 return QskIntervalF( v1, v2 );
212}
213
214bool QskIntervalF::fuzzyContains( qreal value ) const
215{
216 if ( !isValid() )
217 return false;
218
219 if ( ( value < m_lowerBound ) && !qskFuzzyCompare( value, m_lowerBound ) )
220 return false;
221
222 if ( ( value > m_upperBound ) && !qskFuzzyCompare( value, m_upperBound ) )
223 return false;
224
225 return true;
226}
227
228bool QskIntervalF::fuzzyContains( const QskIntervalF& interval ) const
229{
230 if ( !isValid() || !interval.isValid() )
231 return false;
232
233 if ( ( interval.m_lowerBound < m_lowerBound )
234 && !qskFuzzyCompare( interval.m_lowerBound, m_lowerBound ) )
235 {
236 return false;
237 }
238
239 if ( ( interval.m_upperBound > m_upperBound )
240 && !qskFuzzyCompare( interval.m_upperBound, m_upperBound ) )
241 {
242 return false;
243 }
244
245 return true;
246}
247
248bool QskIntervalF::fuzzyIsBoundary( qreal value ) const
249{
250 return qskFuzzyCompare( value, m_lowerBound )
251 || qskFuzzyCompare( value, m_upperBound );
252}
253
254QRectF QskIntervalF::toRect( const QskIntervalF& intervalX,
255 const QskIntervalF& intervalY ) noexcept
256{
257 return QRectF( intervalX.lowerBound(), intervalY.lowerBound(),
258 intervalX.length(), intervalY.length() ).normalized();
259}
260
261#ifndef QT_NO_DEBUG_STREAM
262
263#include <qdebug.h>
264
265QDebug operator<<( QDebug debug, const QskIntervalF& interval )
266{
267 debug.nospace() << "QskIntervalF("
268 << interval.lowerBound() << "," << interval.upperBound() << ")";
269
270 return debug.space();
271}
272
273#endif
274
275#include "moc_QskIntervalF.cpp"