Added colour mixing and various number funcs.

This commit is contained in:
flash 2023-09-15 22:02:23 +00:00
parent f71f3fcf9e
commit 6e4d155536
4 changed files with 93 additions and 3 deletions

View file

@ -1 +1 @@
0.2309.112008
0.2309.152202

View file

@ -1,11 +1,12 @@
<?php
// Colour.php
// Created: 2023-01-02
// Updated: 2023-01-02
// Updated: 2023-09-15
namespace Index\Colour;
use Stringable;
use Index\XNumber;
abstract class Colour implements Stringable {
public abstract function getRed(): int;
@ -44,6 +45,24 @@ abstract class Colour implements Stringable {
return self::$none;
}
public static function mix(Colour $colour1, Colour $colour2, float $weight): Colour {
$weight = min(1, max(0, $weight));
if(XNumber::almostEquals($weight, 0.0))
return $colour1;
if(XNumber::almostEquals($weight, 1.0))
return $colour2;
if($colour1->shouldInherit() || $colour2->shouldInherit())
return self::none();
return new ColourRGB(
(int)round(XNumber::weighted($colour2->getRed(), $colour1->getRed(), $weight)),
(int)round(XNumber::weighted($colour2->getGreen(), $colour1->getGreen(), $weight)),
(int)round(XNumber::weighted($colour2->getBlue(), $colour1->getBlue(), $weight)),
XNumber::weighted($colour2->getAlpha(), $colour1->getAlpha(), $weight),
);
}
private const MSZ_INHERIT = 0x40000000;
public static function fromMisuzu(int $raw): Colour {

29
src/XNumber.php Normal file
View file

@ -0,0 +1,29 @@
<?php
// XNumber.php
// Created: 2023-09-15
// Updated: 2023-09-15
namespace Index;
use InvalidArgumentException;
/**
* Provides various helper methods for numbers.
*/
final class XNumber {
public static function weighted(float $num1, float $num2, float $weight): float {
$weight = min(1, max(0, $weight));
return ($num1 * $weight) + ($num2 * (1 - $weight));
}
public static function almostEquals(float $value1, float $value2): bool {
return abs($value1 - $value2) <= PHP_FLOAT_EPSILON;
}
public static function easeInQuad(float $n): float {
return $n * $n;
}
public static function easeOutQuad(float $n): float {
return 1 - (1 - $n) * (1 - $n);
}
}

View file

@ -1,7 +1,7 @@
<?php
// ColourTest.php
// Created: 2023-01-02
// Updated: 2023-01-02
// Updated: 2023-09-15
declare(strict_types=1);
@ -507,4 +507,46 @@ final class ColourTest extends TestCase {
$this->assertEquals(140, $colour->getGreen());
$this->assertEquals(166, $colour->getBlue());
}
public function testMix(): void {
// none should always return none if involved...
$mixed = Colour::mix(Colour::none(), Colour::parse('lemonchiffon'), 0.243);
$this->assertTrue($mixed->shouldInherit());
$mixed = Colour::mix(Colour::parse('powderblue'), Colour::none(), 0.76);
$this->assertTrue($mixed->shouldInherit());
// ...unless absolute 0 or 1
$mixed = Colour::mix(Colour::none(), Colour::parse('lemonchiffon'), 1.0);
$this->assertFalse($mixed->shouldInherit());
$mixed = Colour::mix(Colour::parse('powderblue'), Colour::none(), 0.0);
$this->assertFalse($mixed->shouldInherit());
// probably a pretty naive test but its better than nothing
$mixed = Colour::mix(new ColourRGB(0, 100, 50), new ColourRGB(100, 0, 50), 0.5);
$this->assertEquals(50, $mixed->getRed());
$this->assertEquals(50, $mixed->getGreen());
$this->assertEquals(50, $mixed->getBlue());
// absolutes should return one of the args
$colour1 = Colour::parse('royalblue');
$colour2 = Colour::parse('tomato');
$this->assertSame($colour1, Colour::mix($colour1, $colour2, 0.0));
$this->assertSame($colour2, Colour::mix($colour1, $colour2, 1.0));
$mixed = Colour::mix($colour1, $colour2, 0.5);
$this->assertEquals(160, $mixed->getRed());
$this->assertEquals(102, $mixed->getGreen());
$this->assertEquals(148, $mixed->getBlue());
$mixed = Colour::mix($colour1, $colour2, 0.2);
$this->assertEquals(103, $mixed->getRed());
$this->assertEquals(104, $mixed->getGreen());
$this->assertEquals(194, $mixed->getBlue());
$mixed = Colour::mix($colour1, $colour2, 0.8);
$this->assertEquals(217, $mixed->getRed());
$this->assertEquals(100, $mixed->getGreen());
$this->assertEquals(102, $mixed->getBlue());
}
}