Passed
Push — 4.0.x ( 414ad0...5c8c8d )
by Doug
05:04 queued 12s
created

GeographicPolygon::createFromArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\Geometry;
10
11
use function count;
12
use InvalidArgumentException;
13
use function max;
14
use function min;
15
use PHPCoord\CoordinateOperation\GeographicValue;
16
use PHPCoord\UnitOfMeasure\Angle\Degree;
17
18
/**
19
 * @internal for now
20
 */
21
class GeographicPolygon
22
{
23
    protected array $vertices;
24
25
    protected bool $crossesAntimeridian;
26
27 73
    protected function __construct(array $vertices, bool $crossesAntimeridian)
28
    {
29 73
        if (count($vertices) !== 4) {
30
            throw new InvalidArgumentException('A bounding box must have exactly 4 vertices (be rectangular)');
31
        }
32 73
        $this->vertices = $vertices;
33 73
        $this->crossesAntimeridian = $crossesAntimeridian;
34
35 73
        if ($this->crossesAntimeridian) { //convert polygon to be antimeridian based
36 7
            foreach ($this->vertices as &$vertex) {
37 7
                $vertex[0] += 180;
38 7
                if ($vertex[0] > 180) {
39 7
                    $vertex[0] -= 360;
40
                }
41
            }
42
        }
43 73
    }
44
45
    /**
46
     * @param array<Degree,Degree> $vertices [[long,lat], [long,lat]...]
47
     */
48 71
    public static function createFromArray(array $vertices, bool $crossesAntimeridian): self
49
    {
50 71
        return new self($vertices, $crossesAntimeridian);
51
    }
52
53 2
    public static function createWorld(): self
54
    {
55 2
        return new self([[-180, -90], [-180, 90], [180, 90], [180, -90]], false);
56
    }
57
58 18
    public function containsPoint(GeographicValue $point): bool
59
    {
60 18
        if ($this->crossesAntimeridian) {
61 2
            $longitude = $point->getLongitude()->add(new Degree(180));
62 2
            $point = new GeographicValue($point->getLatitude(), $longitude, $point->getHeight(), $point->getDatum());
63
        }
64
65 18
        [$lon1, $lat1] = $this->vertices[0];
66 18
        [$lon2, $lat2] = $this->vertices[2];
67 18
        $west = min($lon1, $lon2);
68 18
        $east = max($lon1, $lon2);
69 18
        $south = min($lat1, $lat2);
70 18
        $north = max($lat1, $lat2);
71
72 18
        $latitude = $point->getLatitude()->asDegrees()->getValue();
73 18
        $longitude = $point->getLongitude()->asDegrees()->getValue();
74
75 18
        return $latitude <= $north && $latitude >= $south && $longitude >= $west && $longitude <= $east;
76
    }
77
78
    public function getCentre(): array
79
    {
80
        [$west, $south] = $this->vertices[0];
81
        [$east, $north] = $this->vertices[2];
82
83
        $latitude = new Degree(($north + $south) / 2);
84
        $longitude = new Degree(($west + $east) / 2);
85
        if ($this->crossesAntimeridian) {
86
            $longitude = $longitude->subtract(new Degree(180));
87
        }
88
89
        return [$latitude, $longitude];
90
    }
91
}
92