Failed Conditions
Push — dev ( 5f5cb9...8ee5b7 )
by Jordan
03:10
created

CartesianCoordinate::getPlanarAngle()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
nc 3
nop 0
dl 0
loc 9
ccs 0
cts 7
cp 0
crap 12
rs 10
c 1
b 0
f 0
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 6
    public function __construct($x, $y = null, $z = null)
18
    {
19
        $data = [
20 6
            'x' => $x
21
        ];
22
23 6
        if (!is_null($y)) {
24 6
            $data['y'] = $y;
25 6
            if (!is_null($z)) {
26 6
                $data['z'] = $z;
27
            }
28
        } else {
29
            if (!is_null($z)) {
30
                $data['y'] = $z;
31
            }
32
        }
33
34 6
        parent::__construct($data);
35 6
    }
36
37 1
    public function getAxis($axis): ImmutableDecimal
38
    {
39 1
        if (is_int($axis)) {
40
            $axisIndex = $axis;
41
        } else {
42 1
            $axisIndex = $this->parameters[$axis];
43
        }
44
45 1
        if (!$this->values->hasIndex($axisIndex)) {
46
            return Numbers::makeZero();
47
        }
48
49 1
        return $this->getAxisByIndex($axisIndex);
50
    }
51
52 5
    public function getDistanceFromOrigin(): ImmutableDecimal
53
    {
54 5
        $x = 0;
55
56 5
        if ($this->numberOfDimensions() > 1) {
57 5
            $y = 0;
58
        } else {
59
            $y = null;
60
        }
61
62 5
        if ($this->numberOfDimensions() > 2) {
63
            $z = 0;
64
        } else {
65 5
            $z = null;
66
        }
67
68 5
        return $this->distanceTo(new CartesianCoordinate($x, $y, $z));
69
    }
70
71 5
    public function distanceTo(CoordinateInterface $coordinate): ImmutableDecimal
72
    {
73 5
        if (!($coordinate instanceof CartesianCoordinate)) {
74
            $coordinate = $coordinate->asCartesian();
75
        }
76
77
        /** @var ImmutableDecimal $n */
78 5
        $n = Numbers::makeZero();
79
80 5
        $firstValues = ($this->numberOfDimensions() >= $coordinate->numberOfDimensions()) ? $this->axesValues() : $coordinate->axesValues();
81 5
        $secondValues = ($this->numberOfDimensions() >= $coordinate->numberOfDimensions()) ? $coordinate->axesValues() : $this->axesValues();
82
83 5
        foreach ($firstValues as $index => $value) {
84 5
            $n = $n->add($secondValues[$index]->subtract($value)->pow(2));
85
        }
86
87 5
        $n = $n->sqrt();
88
89 5
        return $n;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $n could return the type Samsara\Fermat\Values\ImmutableComplexNumber which is incompatible with the type-hinted return Samsara\Fermat\Values\ImmutableDecimal. Consider adding an additional type-check to rule them out.
Loading history...
90
    }
91
92
    public function asCartesian(): CartesianCoordinate
93
    {
94
        return $this;
95
    }
96
97
    public function getPolarAngle(): ImmutableDecimal
98
    {
99
        if ($this->numberOfDimensions() == 2) {
100
            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

100
            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...
101
        } elseif ($this->numberOfDimensions() == 3) {
102
            return $this->asSpherical()->getPolarAngle();
103
        } else {
104
            throw new IncompatibleObjectState(
105
                'Can only get a polar angle for a CartesianCoordinate of 2 or 3 dimensions.'
106
            );
107
        }
108
    }
109
110
    public function getPlanarAngle(): ImmutableDecimal
111
    {
112
        if ($this->numberOfDimensions() == 2) {
113
            return $this->getPolarAngle();
114
        } elseif ($this->numberOfDimensions() == 3) {
115
            return $this->asSpherical()->getPlanarAngle();
116
        } else {
117
            throw new IncompatibleObjectState(
118
                'Can only get a planar angle for a CartesianCoordinate of 2 or 3 dimensions.'
119
            );
120
        }
121
    }
122
123
    public function asSpherical(): SphericalCoordinate
124
    {
125
        if ($this->numberOfDimensions() != 3) {
126
            throw new IncompatibleObjectState(
127
                'Attempted to get CartesianCoordinate as SphericalCoordinate without the correct number of dimensions.'
128
            );
129
        }
130
131
        $rho = $this->getDistanceFromOrigin();
132
        $theta = '';
133
        $phi = '';
134
135
        return new SphericalCoordinate($rho, $theta, $phi);
136
    }
137
138
    public function asCylindrical(): CylindricalCoordinate
139
    {
140
        if ($this->numberOfDimensions() != 3) {
141
            throw new IncompatibleObjectState(
142
                'Attempted to get CartesianCoordinate as CylindricalCoordinate without the correct number of dimensions.'
143
            );
144
        }
145
146
        $z = $this->values->get(2);
147
        $r = $this->distanceTo(new CartesianCoordinate([0, 0, $z]));
148
        $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

148
        $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...
149
150
        return new CylindricalCoordinate($r, $theta, $z);
151
    }
152
153 5
    public function asPolar(): PolarCoordinate
154
    {
155 5
        if ($this->numberOfDimensions() != 2) {
156
            throw new IncompatibleObjectState(
157
                'Attempted to get CartesianCoordinate as PolarCoordinate without the correct number of dimensions.'
158
            );
159
        }
160
161 5
        $rho = $this->getDistanceFromOrigin();
162
163 5
        if ($rho->isEqual(0)) {
164
            throw new IncompatibleObjectState(
165
                'Attempted to convert a CartesianCoordinate at the origin into PolarCoordinate'
166
            );
167
        }
168
169
        /** @var ImmutableDecimal $theta */
170 5
        $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

170
        $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...
171 5
        if ($this->values->get(1)->isNegative()) {
172 2
            $theta = $theta->multiply(-1);
173
        }
174
175 5
        return new PolarCoordinate($rho, $theta);
176
    }
177
}