147 lines
4.9 KiB
PHP
147 lines
4.9 KiB
PHP
<?php
|
|
|
|
namespace swf2ass;
|
|
|
|
|
|
use MathPHP\LinearAlgebra\MatrixFactory;
|
|
use swf2ass\math\RealNumber;
|
|
use swf2ass\math\RealMatrix;
|
|
|
|
class MatrixTransform {
|
|
|
|
private RealMatrix $matrix;
|
|
|
|
public function __construct(?Vector2 $scale, ?Vector2 $rotateSkew, ?Vector2 $translation) {
|
|
$this->matrix = new RealMatrix([
|
|
[$scale !== null ? $scale->x : 1 /* a */, /* c */ $rotateSkew !== null ? $rotateSkew->y : 0, 0],
|
|
[$rotateSkew !== null ? $rotateSkew->x : 0 /* b */, /* d */ $scale !== null ? $scale->y : 1, 0],
|
|
[$translation !== null ? $translation->x : 0, $translation !== null ? $translation->y : 0, 1]
|
|
]);
|
|
}
|
|
|
|
public static function fromMatrix(RealMatrix $matrix) : MatrixTransform{
|
|
$o = new MatrixTransform(null, null, null);
|
|
$o->matrix = $matrix;
|
|
return $o;
|
|
}
|
|
|
|
public static function fromArray(array $array) : MatrixTransform{
|
|
return new MatrixTransform(new Vector2($array[0][0], $array[1][1]), new Vector2($array[1][0], $array[0][1]), new Vector2($array[0][2], $array[1][2]));
|
|
}
|
|
|
|
public function toArray(bool $translation = true) : array{
|
|
if($translation){
|
|
return [
|
|
[$this->get_a()->toFixed(), $this->get_b()->toFixed(), 0],
|
|
[$this->get_c()->toFixed(), $this->get_d()->toFixed(), 0],
|
|
[$this->get_tx()->toFixed(), $this->get_ty()->toFixed(), 1]
|
|
];
|
|
}else{
|
|
return [
|
|
[$this->get_a()->toFixed(), $this->get_b()->toFixed(), 0],
|
|
[$this->get_c()->toFixed(), $this->get_d()->toFixed(), 0],
|
|
[0, 0, 1]
|
|
];
|
|
}
|
|
}
|
|
|
|
public static function scale(Vector2 $scale) : MatrixTransform{
|
|
return new MatrixTransform($scale, null, null);
|
|
}
|
|
|
|
//TODO: check sin sign location
|
|
public static function rotate(float $angle) : MatrixTransform{
|
|
$cos = cos($angle);
|
|
$sin = sin($angle);
|
|
return new MatrixTransform(new Vector2($cos, $cos), new Vector2(-$sin, $sin), null);
|
|
}
|
|
|
|
public static function translate(Vector2 $translation) : MatrixTransform{
|
|
return new MatrixTransform(null, null, $translation);
|
|
}
|
|
|
|
public static function identity(): MatrixTransform {
|
|
return new MatrixTransform(null, null, null);
|
|
}
|
|
|
|
public static function skewX(float $angle) : MatrixTransform{
|
|
return new MatrixTransform(null, new Vector2(tan($angle), 0), null);
|
|
}
|
|
|
|
public static function skewY(float $angle) : MatrixTransform{
|
|
return new MatrixTransform(null, new Vector2(0, tan($angle)), null);
|
|
}
|
|
|
|
public function multiply(MatrixTransform $other): MatrixTransform {
|
|
$result = clone $this;
|
|
$result->matrix = $this->matrix->multiply($other->matrix);
|
|
return $result;
|
|
}
|
|
|
|
public function get_a() : RealNumber{
|
|
return $this->matrix->get(0, 0);
|
|
}
|
|
|
|
public function get_b() : RealNumber{
|
|
return $this->matrix->get(1, 0);
|
|
}
|
|
|
|
public function get_c() : RealNumber{
|
|
return $this->matrix->get(0, 1);
|
|
}
|
|
|
|
public function get_d() : RealNumber{
|
|
return $this->matrix->get(1, 1);
|
|
}
|
|
|
|
public function get_tx() : RealNumber{
|
|
return $this->matrix->get(0, 2);
|
|
}
|
|
|
|
public function get_ty() : RealNumber{
|
|
return $this->matrix->get(1, 2);
|
|
}
|
|
|
|
public function getMatrix() : RealMatrix{
|
|
return $this->matrix;
|
|
}
|
|
|
|
public function getTranslation(): Vector2 {
|
|
return $this->applyToVector(new Vector2(0, 0));
|
|
}
|
|
|
|
public function applyToVector(Vector2 $vector, bool $applyTranslation = true): Vector2 {
|
|
if($applyTranslation){
|
|
$result = (new RealMatrix([[$vector->x, $vector->y, 1]]))->multiply($this->matrix);
|
|
}else{
|
|
$result = (new RealMatrix([[$vector->x, $vector->y]]))->multiply($this->matrix->submatrix(0, 0, 1, 1));
|
|
}
|
|
return new Vector2($result->get(0, 0)->toFloat(), $result->get(0, 1)->toFloat());
|
|
}
|
|
|
|
public function applyToShape(Shape $shape, bool $applyTranslation = true): Shape {
|
|
$newShape = new Shape();
|
|
foreach ($shape->getRecords() as $edge) {
|
|
$newShape->addRecord($edge->applyMatrixTransform($this, $applyTranslation));
|
|
}
|
|
|
|
return $newShape;
|
|
}
|
|
|
|
public function equals(MatrixTransform $other): bool {
|
|
return $this->matrix->isEqual($other->matrix, new RealNumber(0.0001));
|
|
}
|
|
|
|
static function fromSWFArray(array $element): MatrixTransform {
|
|
return new MatrixTransform(
|
|
isset($element["scaleX"]) ? new Vector2($element["scaleX"], $element["scaleY"]) : null,
|
|
isset($element["rotateSkew0"]) ? new Vector2($element["rotateSkew1"], $element["rotateSkew0"]) : null,
|
|
isset($element["translateX"]) ? new Vector2($element["translateX"], $element["translateY"]) : null
|
|
);
|
|
}
|
|
|
|
public function __toString() : string{
|
|
return (string) $this->matrix;
|
|
}
|
|
|
|
} |