IndyIndyIndy/landmap-generation

View on GitHub
Classes/Utility/ArrayInterpolator.php

Summary

Maintainability
B
5 hrs
Test Coverage
<?php

namespace ChristianEssl\LandmapGeneration\Utility;

/**
 * ArrayInterpolator
 *
 * Interpolates empty spaces in the given array by looking at each neighbour and calculating a middle value
 */
class ArrayInterpolator
{
    public static function interpolate(array $array, int $width, int $height): array
    {
        foreach (ArrayIterator::getArrayIterator($width, $height) as $x => $y) {
            if (!self::coordinatesExist($array, $x, $y)) {
                $val = self::fillCoordinateFromCorners($array, $width, $height, $x, $y);
                if ($val) {
                    $array[$x][$y] = $val;
                }
            }
        }

        foreach (ArrayIterator::getArrayIterator($width, $height) as $x => $y) {
            if (!self::coordinatesExist($array, $x, $y)) {
                $val = self::fillCoordinateFromAdjacent($array, $width, $height, $x, $y);
                if ($val) {
                    $array[$x][$y] = $val;
                }
            }
        }

        return $array;
    }

    protected static function fillCoordinateFromCorners(array $array, int $width, int $height, int $x, int $y): ?float
    {
        $altitudes = 0;
        $count = 0;

        if ($x > 0) {
            if ($y > 0 && self::coordinatesExist($array, $x - 1, $y - 1)) {
                $altitudes += $array[$x - 1][$y - 1];
                $count++;
            }

            if ($y < ($height - 1) && self::coordinatesExist($array, $x - 1, $y + 1)) {
                $altitudes += $array[$x - 1][$y + 1];
                $count++;
            }
        }

        if ($y > 0) {
            if ($x > 0 && self::coordinatesExist($array, $x - 1, $y - 1)) {
                $altitudes += $array[$x - 1][$y - 1];
                $count++;
            }

            if ($x < ($width - 1) && self::coordinatesExist($array, $x + 1, $y - 1)) {
                $altitudes += $array[$x + 1][$y - 1];
                $count++;
            }
        }

        if ($count > 0) {
            return $altitudes / $count;
        }

        return null;
    }

    protected static function fillCoordinateFromAdjacent(array $array, int $width, int $height, int $x, int $y): ?float
    {
        $altitudes = 0;
        $count = 0;

        if ($x > 0 && self::coordinatesExist($array, $x - 1, $y)) {
            $altitudes += $array[$x - 1][$y];
            $count++;
        }

        if ($x < ($width - 1) && self::coordinatesExist($array, $x + 1, $y)) {
            $altitudes += $array[$x + 1][$y];
            $count++;
        }

        if ($y > 0 && self::coordinatesExist($array, $x, $y - 1)) {
            $altitudes += $array[$x][$y - 1];
            $count++;
        }

        if ($y < ($height - 1) && self::coordinatesExist($array, $x, $y + 1)) {
            $altitudes += $array[$x][$y + 1];
            $count++;
        }

        if ($count > 0) {
            return $altitudes / $count;
        }

        return null;
    }

    protected static function coordinatesExist(array $array, int $x, int $y): bool
    {
        return isset($array[$x][$y]);
    }
}