Passed
Push — master ( aca0dd...3e5121 )
by Doug
22:36
created

interpolateLinearUnitSquare()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 1
nop 3
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 2
rs 10
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\CoordinateOperation;
10
11
use function assert;
12
use function count;
13
use function min;
14
15
trait BilinearInterpolation
16
{
17
    protected float $startX;
18
    protected float $endX;
19
    protected float $startY;
20
    protected float $endY;
21
    protected int $numberOfColumns;
22
    protected int $numberOfRows;
23
    protected float $columnGridInterval;
24
    protected float $rowGridInterval;
25
26 26
    public function interpolateBilinear(
27
        float $x,
28
        float $y
29
    ): array {
30 26
        $corners = $this->getCornersForBilinear($x, $y);
31
32 26
        $dx = ($x - $corners['lowerLeft']->getX()) / ($corners['lowerRight']->getX() - $corners['lowerLeft']->getX());
33 26
        $dy = ($y - $corners['lowerLeft']->getY()) / ($corners['upperLeft']->getY() - $corners['lowerLeft']->getY());
34
35 26
        $interpolations = [];
36 26
        for ($i = 0, $count = count($corners['lowerLeft']->getValues()); $i < $count; ++$i) {
37
            //Interpolate value at lower row
38 26
            $y0 = $this->interpolateLinearUnitSquare($dx, $corners['lowerLeft']->getValues()[$i], $corners['lowerRight']->getValues()[$i]);
39
            //Interpolate value at upper row
40 26
            $y1 = $this->interpolateLinearUnitSquare($dx, $corners['upperLeft']->getValues()[$i], $corners['upperRight']->getValues()[$i]);
41
            //Interpolate between rows
42 26
            $xy = $this->interpolateLinearUnitSquare($dy, $y0, $y1);
43 26
            $interpolations[] = $xy;
44
        }
45
46 26
        return $interpolations;
47
    }
48
49
    /**
50
     * Linear interpolation at point p, where p is between 0 and 1.
51
     */
52 26
    private function interpolateLinearUnitSquare(float $p, float $valueAt0, float $valueAt1): float
53
    {
54 26
        assert($p >= 0 && $p <= 1);
55
56 26
        return $valueAt0 * (1 - $p) + $valueAt1 * $p;
57
    }
58
59
    /**
60
     * @return GridValues[]
61
     */
62 26
    private function getCornersForBilinear(float $x, float $y): array
63
    {
64 26
        $xIndex = (int) (($x - $this->startX) / $this->columnGridInterval);
65 26
        $yIndex = (int) (($y - $this->startY) / $this->rowGridInterval);
66 26
        $xIndexPlus1 = min($xIndex + 1, $this->numberOfColumns);
67 26
        $yIndexPlus1 = min($yIndex + 1, $this->numberOfRows);
68
69
        return [
70 26
            'lowerLeft' => $this->getRecord($xIndex, $yIndex),
0 ignored issues
show
Bug introduced by
It seems like getRecord() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
            'lowerLeft' => $this->/** @scrutinizer ignore-call */ getRecord($xIndex, $yIndex),
Loading history...
71 26
            'lowerRight' => $this->getRecord($xIndexPlus1, $yIndex),
72 26
            'upperLeft' => $this->getRecord($xIndex, $yIndexPlus1),
73 26
            'upperRight' => $this->getRecord($xIndexPlus1, $yIndexPlus1),
74
        ];
75
    }
76
}
77