From d5fef266f5f8d8dd067eda2c6aa07225cb3b7e51 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 29 Jan 2022 20:51:25 +0100 Subject: [PATCH] add matrix cross3 and dot product --- Math/Matrix/Vector.php | 20 ++++++++++ Utils/ArrayUtils.php | 85 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/Math/Matrix/Vector.php b/Math/Matrix/Vector.php index 0f8830b9a..c6aa69079 100644 --- a/Math/Matrix/Vector.php +++ b/Math/Matrix/Vector.php @@ -87,4 +87,24 @@ final class Vector extends Matrix return $this; } + + /** + * Calculate the cross product + * + * @param self $vector 3 Vector + * + * @return Vector + * + * @since 1.0.0 + */ + public function cross3(self $vector) : self + { + $crossArray = [ + $this->getV(1) * $vector->getV(2) - $this->getV(2) * $vector->getV(1), + $this->getV(2) * $vector->getV(0) - $this->getV(0) * $vector->getV(2), + $this->getV(0) * $vector->getV(1) - $this->getV(1) * $vector->getV(0), + ]; + + return self::fromArray($crossArray); + } } diff --git a/Utils/ArrayUtils.php b/Utils/ArrayUtils.php index 888270108..7560a22c0 100644 --- a/Utils/ArrayUtils.php +++ b/Utils/ArrayUtils.php @@ -14,6 +14,8 @@ declare(strict_types=1); namespace phpOMS\Utils; +use phpOMS\Math\Matrix\Exception\InvalidDimensionException; + /** * Array utils. * @@ -452,4 +454,87 @@ final class ArrayUtils return $diff; } + + /** + * Get the dot product of two arrays + * + * @param array $value1 Value 1 is a matrix or a vector + * @param array $value2 Value 2 is a matrix or vector (cannot be a matrix if value1 is a vector) + * + * @return array + * + * @since 1.0.0 + */ + public static function dot(array $value1, array $value2) : int|float|array + { + $m1 = \count($value1); + $n1 = ($isMatrix1 = \is_array($value1[0])) ? \count($value1[0]) : 1; + + $m2 = \count($value2); + $n2 = ($isMatrix2 = \is_array($value2[0])) ? \count($value2[0]) : 1; + + $result = null; + + if ($isMatrix1 && $isMatrix2) { + if ($m2 !== $n1) { + throw new InvalidDimensionException($m2 . 'x' . $n2 . ' not compatible with ' . $m1 . 'x' . $n1); + } + + $result = [[]]; + for ($i = 0; $i < $m1; ++$i) { // Row of 1 + for ($c = 0; $c < $n2; ++$c) { // Column of 2 + $temp = 0; + + for ($j = 0; $j < $m2; ++$j) { // Row of 2 + $temp += $value1[$i][$j] * $value2[$j][$c]; + } + + $result[$i][$c] = $temp; + } + } + } elseif (!$isMatrix1 && !$isMatrix2) { + if ($m1 !== $m2) { + throw new InvalidDimensionException($m1 . ' vs. ' . $m2); + } + + $result = 0; + for ($i = 0; $i < $m1; ++$i) { + $result += $value1[$i] * $value2[$i]; + } + } elseif ($isMatrix1 && !$isMatrix2) { + $result = []; + for ($i = 0; $i < $m1; ++$i) { // Row of 1 + $temp = 0; + + for ($c = 0; $c < $m2; ++$c) { // Row of 2 + $temp += $value1[$i][$c] * $value2[$c]; + } + + $result[$i] = $temp; + } + } else { + throw new \InvalidArgumentException(); + } + + return $result; + } + + /** + * Calculate the vector corss product + * + * @param array $vector1 First 3 vector + * @param array $vector2 Second 3 vector + * + * @return array + * + * @since 1.0.0 + */ + public function cross3(array $vector1, array $vector2) : array + { + return [ + $vector1[1] * $vector2[2] - $vector1[2] * $vector2[1], + $vector1[2] * $vector2[0] - $vector1[0] * $vector2[2], + $vector1[0] * $vector2[1] - $vector1[1] * $vector2[0], + ]; + } }