Passed
Push — 4.x ( 1d49e7...4cde9a )
by Doug
06:44
created

AutoConversion::findOperationPath()   D

Complexity

Conditions 23
Paths 8

Size

Total Lines 61
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 23

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 40
nc 8
nop 2
dl 0
loc 61
ccs 33
cts 33
cp 1
crap 23
rs 4.1666
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\CoordinateOperation;
10
11
use DateTimeImmutable;
12
use PHPCoord\CoordinateReferenceSystem\CoordinateReferenceSystem;
13
use PHPCoord\Exception\UnknownConversionException;
14
use PHPCoord\Point;
15
use PHPCoord\UnitOfMeasure\Time\Year;
16
17
trait AutoConversion
18
{
19 11
    public function convert(CoordinateReferenceSystem $to, bool $ignoreBoundaryRestrictions = false): Point
20
    {
21 11
        if ($this->getCRS() == $to) {
22 1
            return $this;
23
        }
24
25 10
        if (strpos($this->getCRS()->getSRID(), CoordinateReferenceSystem::CRS_SRID_PREFIX_EPSG) !== 0 || strpos($to->getSRID(), CoordinateReferenceSystem::CRS_SRID_PREFIX_EPSG) !== 0) {
26
            throw new UnknownConversionException('Automatic conversions are only supported for EPSG CRSs');
27
        }
28
29 10
        $point = $this;
30 10
        $path = $this->findOperationPath($to, $ignoreBoundaryRestrictions);
31
32 8
        $inReverse = reset($path)['source_crs'] !== $this->getCRS()->getSRID();
33
34 8
        foreach ($path as $step) {
35 8
            $target = CoordinateReferenceSystem::fromSRID($inReverse ? $step['source_crs'] : $step['target_crs']);
36 8
            $point = $point->performOperation($step['operation'], $target, $inReverse);
37
        }
38
39 8
        return $point;
40
    }
41
42 10
    protected function findOperationPath(CoordinateReferenceSystem $to, bool $ignoreBoundaryRestrictions): array
43
    {
44 10
        $candidates = [];
45 10
        foreach (CRSTransformations::getSupportedTransformations() as $transformation) {
46 10
            if ($transformation['source_crs'] === $this->getCRS()->getSRID() && $transformation['target_crs'] === $to->getSRID()) {
47 9
                $candidates[] = $transformation;
48 10
            } elseif ($transformation['target_crs'] === $this->getCRS()->getSRID() && $transformation['source_crs'] === $to->getSRID() && $transformation['reversible']) {
49 1
                $candidates[] = $transformation;
50
            }
51
        }
52
53 10
        $asGeog = $this->asGeographicValue();
54 10
        $lat = $asGeog->getLatitude()->asDegrees()->getValue();
55 10
        $long = $asGeog->getLongitude()->asDegrees()->getValue();
56 10
        $candidates = array_filter($candidates, function (array $candidate) use ($lat, $long, $ignoreBoundaryRestrictions) {
57 10
            $operation = CoordinateOperations::getOperationData($candidate['operation']);
0 ignored issues
show
Bug introduced by
The type PHPCoord\CoordinateOperation\CoordinateOperations was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
58 10
            $ok = true;
59
60 10
            if (!$ignoreBoundaryRestrictions) {
61
                //filter out operations that only operate outside this point
62 9
                if ($operation['bounding_box']['east'] < $operation['bounding_box']['west']) {
63 1
                    $ok = $ok && $lat <= $operation['bounding_box']['north'] && $lat >= $operation['bounding_box']['south'] && $long >= $operation['bounding_box']['west'] && $long <= ($operation['bounding_box']['east'] + 360);
64
                } else {
65 8
                    $ok = $ok && $lat <= $operation['bounding_box']['north'] && $lat >= $operation['bounding_box']['south'] && $long >= $operation['bounding_box']['west'] && $long <= $operation['bounding_box']['east'];
66
                }
67
            }
68
69
            //filter out operations that require an epoch if we don't have one
70 10
            if (!$this->getCoordinateEpoch() && in_array($operation['method'], [
71 9
                    CoordinateOperationMethods::EPSG_TIME_DEPENDENT_COORDINATE_FRAME_ROTATION_GEOCEN,
72
                    CoordinateOperationMethods::EPSG_TIME_DEPENDENT_COORDINATE_FRAME_ROTATION_GEOG2D,
73
                    CoordinateOperationMethods::EPSG_TIME_DEPENDENT_COORDINATE_FRAME_ROTATION_GEOG3D,
74
                    CoordinateOperationMethods::EPSG_TIME_DEPENDENT_POSITION_VECTOR_TFM_GEOCENTRIC,
75
                    CoordinateOperationMethods::EPSG_TIME_DEPENDENT_POSITION_VECTOR_TFM_GEOG2D,
76
                    CoordinateOperationMethods::EPSG_TIME_DEPENDENT_POSITION_VECTOR_TFM_GEOG3D,
77
                    CoordinateOperationMethods::EPSG_TIME_SPECIFIC_COORDINATE_FRAME_ROTATION_GEOCEN,
78
                    CoordinateOperationMethods::EPSG_TIME_SPECIFIC_POSITION_VECTOR_TRANSFORM_GEOCEN,
79 10
                ], true)) {
80 1
                $ok = false;
81
            }
82
83
            //filter out operations that require a specific epoch
84 10
            if ($this->getCoordinateEpoch() && in_array($operation['method'], [
85 1
                    CoordinateOperationMethods::EPSG_TIME_SPECIFIC_COORDINATE_FRAME_ROTATION_GEOCEN,
86
                    CoordinateOperationMethods::EPSG_TIME_SPECIFIC_POSITION_VECTOR_TRANSFORM_GEOCEN,
87 10
                ], true)) {
88 1
                $params = CoordinateOperationParams::getParamData($candidate['operation']);
0 ignored issues
show
Bug introduced by
The type PHPCoord\CoordinateOpera...ordinateOperationParams was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
89 1
                $pointEpoch = Year::fromDateTime($this->getCoordinateEpoch());
90 1
                $ok = $ok && (abs($pointEpoch->getValue() - $params['Transformation reference epoch']['value']) <= 0.001);
91
            }
92
93 10
            return $ok;
94 10
        });
95
96 10
        usort($candidates, static function (array $a, array $b) { return $a['accuracy'] <=> $b['accuracy']; });
97
98 10
        if (!$candidates) {
99 2
            throw new UnknownConversionException('Unable to perform conversion, please file a bug if you think this is incorrect');
100
        }
101
102 8
        return [reset($candidates)];
103
    }
104
105
    abstract public function getCRS(): CoordinateReferenceSystem;
106
107
    abstract public function getCoordinateEpoch(): ?DateTimeImmutable;
108
109
    abstract public function asGeographicValue(): GeographicValue;
110
111
    abstract protected function performOperation(string $srid, CoordinateReferenceSystem $to, bool $inReverse): Point;
112
}
113