Skip to content

Commit 918af4f

Browse files
committed
More tests
1 parent 9d4cddd commit 918af4f

File tree

3 files changed

+724
-11
lines changed

3 files changed

+724
-11
lines changed

modules/yup_graphics/primitives/yup_AffineTransform.h

Lines changed: 121 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
==============================================================================
33
44
This file is part of the YUP library.
5-
Copyright (c) 2024 - [email protected]
5+
Copyright (c) 2025 - [email protected]
66
77
YUP is an open source library subject to open-source licensing.
88
@@ -207,6 +207,111 @@ class YUP_API AffineTransform
207207
return { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f };
208208
}
209209

210+
//==============================================================================
211+
/** Check if the transformation only contains translation
212+
213+
Checks if the AffineTransform object represents only a translation transformation,
214+
with no rotation, scaling, or shearing applied.
215+
216+
@return True if this is only a translation transformation, false otherwise.
217+
*/
218+
constexpr bool isOnlyTranslation() const noexcept
219+
{
220+
return approximatelyEqual (scaleX, 1.0f)
221+
&& approximatelyEqual (shearX, 0.0f)
222+
&& approximatelyEqual (shearY, 0.0f)
223+
&& approximatelyEqual (scaleY, 1.0f);
224+
}
225+
226+
/** Check if the transformation only contains rotation
227+
228+
Checks if the AffineTransform object represents only a rotation transformation,
229+
with no translation, scaling, or shearing applied. A pure rotation maintains unit
230+
determinant and has orthonormal basis vectors.
231+
232+
@return True if this is only a rotation transformation, false otherwise.
233+
*/
234+
constexpr bool isOnlyRotation() const noexcept
235+
{
236+
if (! approximatelyEqual (translateX, 0.0f) || ! approximatelyEqual (translateY, 0.0f))
237+
return false;
238+
239+
const float det = getDeterminant();
240+
const float col1LengthSq = scaleX * scaleX + shearY * shearY;
241+
const float col2LengthSq = shearX * shearX + scaleY * scaleY;
242+
243+
constexpr float rotationTolerance = 0.0001f;
244+
return yup_abs (det - 1.0f) < rotationTolerance
245+
&& yup_abs (col1LengthSq - 1.0f) < rotationTolerance
246+
&& yup_abs (col2LengthSq - 1.0f) < rotationTolerance;
247+
}
248+
249+
/** Check if the transformation only contains uniform scaling
250+
251+
Checks if the AffineTransform object represents only a uniform scaling transformation,
252+
with no translation, rotation, or shearing applied. Uniform scaling has equal scale
253+
factors in both x and y directions.
254+
255+
@return True if this is only a uniform scaling transformation, false otherwise.
256+
*/
257+
constexpr bool isOnlyUniformScaling() const noexcept
258+
{
259+
return approximatelyEqual (translateX, 0.0f)
260+
&& approximatelyEqual (translateY, 0.0f)
261+
&& approximatelyEqual (shearX, 0.0f)
262+
&& approximatelyEqual (shearY, 0.0f)
263+
&& approximatelyEqual (scaleX, scaleY)
264+
&& ! approximatelyEqual (scaleX, 1.0f);
265+
}
266+
267+
/** Check if the transformation only contains non-uniform scaling
268+
269+
Checks if the AffineTransform object represents only a non-uniform scaling transformation,
270+
with no translation, rotation, or shearing applied. Non-uniform scaling has different
271+
scale factors in x and y directions.
272+
273+
@return True if this is only a non-uniform scaling transformation, false otherwise.
274+
*/
275+
constexpr bool isOnlyNonUniformScaling() const noexcept
276+
{
277+
return approximatelyEqual (translateX, 0.0f)
278+
&& approximatelyEqual (translateY, 0.0f)
279+
&& approximatelyEqual (shearX, 0.0f)
280+
&& approximatelyEqual (shearY, 0.0f)
281+
&& ! approximatelyEqual (scaleX, scaleY)
282+
&& ! approximatelyEqual (scaleX, 1.0f)
283+
&& ! approximatelyEqual (scaleY, 1.0f);
284+
}
285+
286+
/** Check if the transformation only contains scaling (uniform or non-uniform)
287+
288+
Checks if the AffineTransform object represents only a scaling transformation,
289+
with no translation, rotation, or shearing applied.
290+
291+
@return True if this is only a scaling transformation, false otherwise.
292+
*/
293+
constexpr bool isOnlyScaling() const noexcept
294+
{
295+
return isOnlyUniformScaling() || isOnlyNonUniformScaling();
296+
}
297+
298+
/** Check if the transformation only contains shearing
299+
300+
Checks if the AffineTransform object represents only a shearing transformation,
301+
with no translation, rotation, or scaling applied. A pure shear maintains unit
302+
scale factors.
303+
304+
@return True if this is only a shearing transformation, false otherwise.
305+
*/
306+
constexpr bool isOnlyShearing() const noexcept
307+
{
308+
return approximatelyEqual (translateX, 0.0f)
309+
&& approximatelyEqual (translateY, 0.0f)
310+
&& approximatelyEqual (scaleX, 1.0f)
311+
&& approximatelyEqual (scaleY, 1.0f)
312+
&& (! approximatelyEqual (shearX, 0.0f) || ! approximatelyEqual (shearY, 0.0f));
313+
}
314+
210315
//==============================================================================
211316
/** Create an inverted transformation
212317
@@ -654,14 +759,21 @@ class YUP_API AffineTransform
654759
*/
655760
[[nodiscard]] constexpr AffineTransform prependedBy (const AffineTransform& other) const noexcept
656761
{
657-
return {
658-
scaleX * other.scaleX + shearX * other.shearY,
659-
shearX * other.scaleX + scaleY * other.shearY,
660-
translateX * other.scaleX + translateY * other.shearY + other.translateX,
661-
scaleX * other.shearX + shearY * other.scaleY,
662-
shearX * other.shearX + scaleY * other.scaleY,
663-
translateX * other.shearX + translateY * other.scaleY + other.translateY
664-
};
762+
return other.followedBy (*this);
763+
}
764+
765+
//==============================================================================
766+
/** Create a transformation that follows another.
767+
768+
Creates a new AffineTransform object that represents this transformation followed by another specified AffineTransform.
769+
770+
@param other The AffineTransform to follow this one.
771+
772+
@return A new AffineTransform object representing the combined transformation.
773+
*/
774+
[[nodiscard]] constexpr AffineTransform operator* (const AffineTransform& other) const noexcept
775+
{
776+
return followedBy (other);
665777
}
666778

667779
//==============================================================================

0 commit comments

Comments
 (0)