Test Failed
Pull Request — master (#47)
by Jordan
14:20
created

CartesianCoordinate::distanceTo()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
c 1
b 0
f 0
nc 16
nop 1
dl 0
loc 19
rs 9.6111
1
<?php
2
3
namespace Samsara\Fermat\Values\Geometry\CoordinateSystems;
4
5
use Samsara\Exceptions\SystemError\LogicalError\IncompatibleObjectState;
6
use Samsara\Exceptions\UsageError\IntegrityConstraint;
7
use Samsara\Fermat\Numbers;
8
use Samsara\Fermat\Types\Base\Interfaces\Coordinates\CoordinateInterface;
9
use Samsara\Fermat\Types\Base\Interfaces\Coordinates\ThreeDCoordinateInterface;
10
use Samsara\Fermat\Types\Base\Interfaces\Coordinates\TwoDCoordinateInterface;
11
use Samsara\Fermat\Types\Coordinate;
12
use Samsara\Fermat\Values\ImmutableDecimal;
13
14
class CartesianCoordinate extends Coordinate implements TwoDCoordinateInterface, ThreeDCoordinateInterface
15
{
16
17
    public function __construct($x, $y = null, $z = null)
18
    {
19
        $data = [
20
            'x' => $x
21
        ];
22
23
        if (!is_null($y)) {
24
            $data['y'] = $y;
25
            if (!is_null($z)) {
26
                $data['z'] = $z;
27
            }
28
        } else {
29
            if (!is_null($z)) {
30
                $data['y'] = $z;
31
            }
32
        }
33
34
        parent::__construct($data);
35
    }
36
37
    public function getAxis($axis): ImmutableDecimal
38
    {
39
        if (!$this->values->hasIndex($this->parameters[$axis])) {
40
            return Numbers::makeZero();
41
        }
42
43
        return parent::getAxis($axis);
44
    }
45
46
    public function getDistanceFromOrigin(): ImmutableDecimal
47
    {
48
        $origin = [];
49
50
        foreach ($this->parameters as $key => $valueKey) {
51
            $origin[$key] = 0;
52
        }
53
54
        return $this->distanceTo(new CartesianCoordinate($origin));
55
    }
56
57
    public function distanceTo(CoordinateInterface $coordinate): ImmutableDecimal
58
    {
59
        if (!($coordinate instanceof CartesianCoordinate)) {
60
            $coordinate = $coordinate->asCartesian();
61
        }
62
63
        /** @var ImmutableDecimal $n */
64
        $n = Numbers::makeZero();
65
66
        $firstValues = ($this->numberOfDimensions() >= $coordinate->numberOfDimensions()) ? $this->axesValues() : $coordinate->axesValues();
67
        $secondValues = ($this->numberOfDimensions() >= $coordinate->numberOfDimensions()) ? $coordinate : $this;
68
69
        foreach ($firstValues as $index => $value) {
70
            $n = $n->add($secondValues->getAxis($index)->subtract($value)->pow(2));
71
        }
72
73
        $n = $n->sqrt();
74
75
        return $n;
76
    }
77
78
    public function asCartesian(): CartesianCoordinate
79
    {
80
        return $this;
81
    }
82
83
    public function getPolarAngle(): ImmutableDecimal
84
    {
85
        if ($this->numberOfDimensions() == 2) {
86
            return $this->asPolar()->getAngleOfRotation();
0 ignored issues
show
Bug introduced by
The method getAngleOfRotation() does not exist on Samsara\Fermat\Values\Ge...Systems\PolarCoordinate. ( Ignorable by Annotation )

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

86
            return $this->asPolar()->/** @scrutinizer ignore-call */ getAngleOfRotation();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
87
        } elseif ($this->numberOfDimensions() == 3) {
88
            return $this->asSpherical()->getPolarAngle();
89
        } else {
90
            throw new IncompatibleObjectState(
91
                'Can only get a polar angle for a CartesianCoordinate of 2 or 3 dimensions.'
92
            );
93
        }
94
    }
95
96
    public function getPlanarAngle(): ImmutableDecimal
97
    {
98
        if ($this->numberOfDimensions() == 2) {
99
            return $this->getPolarAngle();
100
        } elseif ($this->numberOfDimensions() == 3) {
101
            return $this->asSpherical()->getPlanarAngle();
102
        } else {
103
            throw new IncompatibleObjectState(
104
                'Can only get a planar angle for a CartesianCoordinate of 2 or 3 dimensions.'
105
            );
106
        }
107
    }
108
109
    public function asSpherical(): SphericalCoordinate
110
    {
111
        if ($this->numberOfDimensions() != 3) {
112
            throw new IncompatibleObjectState(
113
                'Attempted to get CartesianCoordinate as SphericalCoordinate without the correct number of dimensions.'
114
            );
115
        }
116
117
        $rho = $this->getDistanceFromOrigin();
118
        $theta = '';
119
        $phi = '';
120
121
        return new SphericalCoordinate($rho, $theta, $phi);
122
    }
123
124
    public function asCylindrical(): CylindricalCoordinate
125
    {
126
        if ($this->numberOfDimensions() != 3) {
127
            throw new IncompatibleObjectState(
128
                'Attempted to get CartesianCoordinate as CylindricalCoordinate without the correct number of dimensions.'
129
            );
130
        }
131
132
        $z = $this->values->get(2);
133
        $r = $this->distanceTo(new CartesianCoordinate([0, 0, $z]));
134
        $theta = $this->values->get(1)->divide($this->values->get(0))->arctan();
0 ignored issues
show
Bug introduced by
The method arctan() does not exist on Samsara\Fermat\Values\ImmutableComplexNumber. ( Ignorable by Annotation )

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

134
        $theta = $this->values->get(1)->divide($this->values->get(0))->/** @scrutinizer ignore-call */ arctan();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
135
136
        return new CylindricalCoordinate($r, $theta, $z);
137
    }
138
139
    public function asPolar(): PolarCoordinate
140
    {
141
        if ($this->numberOfDimensions() != 2) {
142
            throw new IncompatibleObjectState(
143
                'Attempted to get CartesianCoordinate as PolarCoordinate without the correct number of dimensions.'
144
            );
145
        }
146
147
        $rho = $this->getDistanceFromOrigin();
148
149
        if ($rho->isEqual(0)) {
150
            throw new IncompatibleObjectState(
151
                'Attempted to convert a CartesianCoordinate at the origin into PolarCoordinate'
152
            );
153
        }
154
155
        /** @var ImmutableDecimal $theta */
156
        $theta = $this->values->get(0)->divide($rho)->arccos();
0 ignored issues
show
Bug introduced by
The method arccos() does not exist on Samsara\Fermat\Values\ImmutableComplexNumber. ( Ignorable by Annotation )

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

156
        $theta = $this->values->get(0)->divide($rho)->/** @scrutinizer ignore-call */ arccos();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
157
        if ($this->values->get(1)->isNegative()) {
158
            $theta = $theta->multiply(-1);
159
        }
160
161
        return new PolarCoordinate($rho, $theta);
162
    }
163
}