78 lines
2.7 KiB
PHP
78 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit;
|
|
|
|
use App\Services\ThreeMfTransform;
|
|
use RuntimeException;
|
|
use Tests\TestCase;
|
|
|
|
class ThreeMfTransformTest extends TestCase
|
|
{
|
|
public function test_identity_leaves_a_point_unchanged(): void
|
|
{
|
|
$this->assertSame([1.0, 2.0, 3.0], ThreeMfTransform::apply(ThreeMfTransform::identity(), [1.0, 2.0, 3.0]));
|
|
}
|
|
|
|
public function test_parses_twelve_space_separated_floats(): void
|
|
{
|
|
$matrix = ThreeMfTransform::parse('1 0 0 0 1 0 0 0 1 10 20 30');
|
|
|
|
$this->assertSame([10.0, 20.0, 33.0], ThreeMfTransform::apply($matrix, [0.0, 0.0, 3.0]));
|
|
}
|
|
|
|
public function test_rejects_a_transform_without_exactly_twelve_values(): void
|
|
{
|
|
$this->expectException(RuntimeException::class);
|
|
ThreeMfTransform::parse('1 0 0 0 1 0 0 0 1');
|
|
}
|
|
|
|
public function test_rejects_a_non_numeric_transform_value(): void
|
|
{
|
|
$this->expectException(RuntimeException::class);
|
|
ThreeMfTransform::parse('1 0 0 0 1 0 0 0 1 x 0 0');
|
|
}
|
|
|
|
public function test_rejects_a_non_finite_transform_value(): void
|
|
{
|
|
$this->expectException(RuntimeException::class);
|
|
ThreeMfTransform::parse('1 0 0 0 1 0 0 0 1 NAN 0 0');
|
|
}
|
|
|
|
public function test_translation_moves_a_point(): void
|
|
{
|
|
$translate = ThreeMfTransform::parse('1 0 0 0 1 0 0 0 1 5 6 7');
|
|
|
|
$this->assertSame([6.0, 8.0, 10.0], ThreeMfTransform::apply($translate, [1.0, 2.0, 3.0]));
|
|
}
|
|
|
|
public function test_scale_multiplies_each_axis(): void
|
|
{
|
|
$scale = ThreeMfTransform::parse('2 0 0 0 3 0 0 0 4 0 0 0');
|
|
|
|
$this->assertSame([2.0, 6.0, 12.0], ThreeMfTransform::apply($scale, [1.0, 2.0, 3.0]));
|
|
}
|
|
|
|
public function test_compose_applies_inner_transform_before_outer(): void
|
|
{
|
|
$translateThenScale = ThreeMfTransform::compose(
|
|
outer: ThreeMfTransform::parse('2 0 0 0 2 0 0 0 2 0 0 0'),
|
|
inner: ThreeMfTransform::parse('1 0 0 0 1 0 0 0 1 10 0 0'),
|
|
);
|
|
|
|
// Expected: apply(outer, apply(inner, p)) = apply(outer, [11,0,0]) = [22,0,0]
|
|
$this->assertSame([22.0, 0.0, 0.0], ThreeMfTransform::apply($translateThenScale, [1.0, 0.0, 0.0]));
|
|
}
|
|
|
|
public function test_compose_matches_applying_each_transform_in_turn_for_an_arbitrary_rotation_like_matrix(): void
|
|
{
|
|
$outer = ThreeMfTransform::parse('0 1 0 -1 0 0 0 0 1 3 4 5');
|
|
$inner = ThreeMfTransform::parse('1 0 0 0 1 0 0 0 1 1 2 3');
|
|
$point = [7.0, -2.0, 0.5];
|
|
|
|
$composed = ThreeMfTransform::compose($outer, $inner);
|
|
|
|
$expected = ThreeMfTransform::apply($outer, ThreeMfTransform::apply($inner, $point));
|
|
$this->assertSame($expected, ThreeMfTransform::apply($composed, $point));
|
|
}
|
|
}
|