Coordinate::__set()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Bavix\Geo;
4
5
use Bavix\Geo\Unit\Distance;
6
use Bavix\Geo\Value\Axis;
7
8
/**
9
 * Class Coordinate
10
 *
11
 * @package Bavix\Geo
12
 *
13
 * @property-read Axis $latitude
14
 * @property-read Axis $longitude
15
 */
16
class Coordinate implements \JsonSerializable
17
{
18
19
    /**
20
     * @var array
21
     */
22
    protected $getter = [
23
        'latitude' => true,
24
        'longitude' => true,
25
    ];
26
27
    /**
28
     * @var Axis
29
     */
30
    protected $latitude;
31
32
    /**
33
     * @var Axis
34
     */
35
    protected $longitude;
36
37
    /**
38
     * Coordinate constructor.
39
     * @param float $latitude
40
     * @param float $longitude
41
     */
42
    public function __construct(float $latitude, float $longitude)
43
    {
44
        $this->latitude = Axis::make();
0 ignored issues
show
Bug introduced by
The property latitude is declared read-only in Bavix\Geo\Coordinate.
Loading history...
45
        $this->latitude->degrees = $latitude;
46
        $this->longitude = Axis::make();
0 ignored issues
show
Bug introduced by
The property longitude is declared read-only in Bavix\Geo\Coordinate.
Loading history...
47
        $this->longitude->degrees = $longitude;
48
    }
49
50
    /**
51
     * @param string $name
52
     *
53
     * @return Axis
54
     */
55
    public function __get($name): Axis
56
    {
57
        if (!isset($this->getter[$name])) {
58
            throw new \InvalidArgumentException(__METHOD__);
59
        }
60
61
        return $this->$name->proxy();
62
    }
63
64
    /**
65
     * @param string $name
66
     * @param mixed $value
67
     *
68
     * @throws \InvalidArgumentException
69
     */
70
    public function __set($name, $value)
71
    {
72
        throw new \InvalidArgumentException(__METHOD__);
73
    }
74
75
    /**
76
     * @param string $name
77
     *
78
     * @return bool
79
     */
80
    public function __isset(string $name): bool
81
    {
82
        return isset($this->getter[$name]);
83
    }
84
85
    /**
86
     * @see https://en.wikipedia.org/wiki/Great-circle_distance
87
     *
88
     * @param self $object
89
     *
90
     * @return Distance
91
     */
92
    public function distanceTo(self $object): Distance
93
    {
94
        $theta = $this->longitude->radian - $object->longitude->radian;
95
        $partSin = \sin($this->latitude->radian) * \sin($object->latitude->radian);
96
        $partCos = \cos($this->latitude->radian) * \cos($object->latitude->radian) * \cos($theta);
97
        $dist = \rad2deg(\acos($partSin + $partCos));
98
        return Distance::fromNauticalMiles($dist * 60.);
99
    }
100
101
    /**
102
     * @param float $latitude
103
     * @param float $longitude
104
     *
105
     * @return static
106
     */
107
    public static function make(float $latitude, float $longitude): self
108
    {
109
        return new static($latitude, $longitude);
110
    }
111
112
    /**
113
     * @param float|Axis $latitude
114
     * @param float|Axis $longitude
115
     * @return static
116
     */
117
    public function plus($latitude, $longitude): self
118
    {
119
        $latitude = \is_object($latitude) ? $latitude->degrees : $latitude;
120
        $longitude = \is_object($longitude) ? $longitude->degrees : $longitude;
121
122
        return static::make(
123
            $this->latitude->degrees + $latitude,
124
            $this->longitude->degrees + $longitude
125
        );
126
    }
127
128
    /**
129
     * @param float|Axis $latitude
130
     * @param float|Axis $longitude
131
     * @return static
132
     */
133
    public function minus($latitude, $longitude): self
134
    {
135
        return $this->plus(
136
            -$latitude,
137
            -$longitude
138
        );
139
    }
140
141
    /**
142
     * @return array
143
     */
144
    public function jsonSerialize(): array
145
    {
146
        return [
147
            'latitude' => $this->latitude,
148
            'longitude' => $this->longitude,
149
        ];
150
    }
151
152
}
153