• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

brick / geo / 13687942239

05 Mar 2025 11:54PM UTC coverage: 84.507% (+0.07%) from 84.44%
13687942239

push

github

BenMorel
Remove Psalm-specific annotations

1560 of 1846 relevant lines covered (84.51%)

1977.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.74
/src/CompoundCurve.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo;
6

7
use ArrayIterator;
8
use Brick\Geo\Exception\CoordinateSystemException;
9
use Brick\Geo\Exception\EmptyGeometryException;
10
use Brick\Geo\Exception\InvalidGeometryException;
11
use Brick\Geo\Exception\NoSuchGeometryException;
12
use Brick\Geo\Projector\Projector;
13
use Override;
14

15
/**
16
 * A CompoundCurve is a collection of zero or more continuous CircularString or LineString instances.
17
 *
18
 * @template-implements \IteratorAggregate<LineString|CircularString>
19
 */
20
final class CompoundCurve extends Curve implements \Countable, \IteratorAggregate
21
{
22
    /**
23
     * The Curves that compose this CompoundCurve.
24
     *
25
     * This array can be empty.
26
     *
27
     * @var list<LineString|CircularString>
28
     */
29
    protected array $curves = [];
30

31
    /**
32
     * The coordinate system of each of the curves must match the one of the CompoundCurve.
33
     *
34
     * @param CoordinateSystem             $cs     The coordinate system of the CompoundCurve.
35
     * @param LineString|CircularString ...$curves The curves that compose the CompoundCurve.
36
     *
37
     * @throws EmptyGeometryException    If any of the input curves is empty.
38
     * @throws InvalidGeometryException  If the compound curve is not continuous.
39
     * @throws CoordinateSystemException If different coordinate systems are used.
40
     */
41
    public function __construct(CoordinateSystem $cs, LineString|CircularString ...$curves)
42
    {
43
        parent::__construct($cs, ! $curves);
2,302✔
44

45
        if (! $curves) {
2,302✔
46
            return;
916✔
47
        }
48

49
        CoordinateSystem::check($this, ...$curves);
1,400✔
50

51
        /** @var Curve|null $previousCurve */
52
        $previousCurve = null;
1,400✔
53

54
        foreach ($curves as $curve) {
1,400✔
55
            if ($previousCurve) {
1,400✔
56
                $endPoint = $previousCurve->endPoint();
1,302✔
57
                $startPoint = $curve->startPoint();
1,302✔
58

59
                if ($endPoint != $startPoint) { // on purpose by-value comparison!
1,302✔
60
                    throw new InvalidGeometryException('Incontinuous compound curve.');
7✔
61
                }
62
            }
63

64
            $previousCurve = $curve;
1,400✔
65
        }
66

67
        $this->curves = array_values($curves);
1,393✔
68
    }
69

70
    /**
71
     * Creates a non-empty CompoundCurve composed of the given curves.
72
     *
73
     * @param LineString|CircularString    $curve1 The first curve.
74
     * @param LineString|CircularString ...$curveN The subsequent curves, if any.
75
     *
76
     * @throws EmptyGeometryException    If any of the input curves is empty.
77
     * @throws InvalidGeometryException  If the compound curve is not continuous.
78
     * @throws CoordinateSystemException If the curves use different coordinate systems.
79
     */
80
    public static function of(LineString|CircularString $curve1, LineString|CircularString ...$curveN) : CompoundCurve
81
    {
82
        return new CompoundCurve($curve1->coordinateSystem(), $curve1, ...$curveN);
×
83
    }
84

85
    #[Override]
86
    public function startPoint() : Point
87
    {
88
        if ($this->isEmpty) {
112✔
89
            throw new EmptyGeometryException('The CompoundCurve is empty and has no start point.');
56✔
90
        }
91

92
        return $this->curves[0]->startPoint();
56✔
93
    }
94

95
    #[Override]
96
    public function endPoint() : Point
97
    {
98
        if ($this->curves === []) {
112✔
99
            throw new EmptyGeometryException('The CompoundCurve is empty and has no end point.');
56✔
100
        }
101

102
        $count = count($this->curves);
56✔
103

104
        return $this->curves[$count - 1]->endPoint();
56✔
105
    }
106

107
    /**
108
     * Returns the number of Curves in this CompoundCurve.
109
     */
110
    public function numCurves() : int
111
    {
112
        return count($this->curves);
56✔
113
    }
114

115
    /**
116
     * Returns the specified Curve N in this CompoundCurve.
117
     *
118
     * @param int $n The curve number, 1-based.
119
     *
120
     * @throws NoSuchGeometryException If there is no Curve at this index.
121
     */
122
    public function curveN(int $n) : LineString|CircularString
123
    {
124
        if (! isset($this->curves[$n - 1])) {
329✔
125
            throw new NoSuchGeometryException('There is no Curve in this CompoundCurve at index ' . $n);
224✔
126
        }
127

128
        return $this->curves[$n - 1];
105✔
129
    }
130

131
    /**
132
     * Returns the curves that compose this CompoundCurve.
133
     *
134
     * @return list<LineString|CircularString>
135
     */
136
    public function curves() : array
137
    {
138
        return $this->curves;
×
139
    }
140

141
    #[Override]
142
    public function geometryType() : string
143
    {
144
        return 'CompoundCurve';
951✔
145
    }
146

147
    #[Override]
148
    public function geometryTypeBinary() : int
149
    {
150
        return Geometry::COMPOUNDCURVE;
448✔
151
    }
152

153
    #[Override]
154
    public function getBoundingBox() : BoundingBox
155
    {
156
        $boundingBox = BoundingBox::new();
×
157

158
        foreach ($this->curves as $curve) {
×
159
            $boundingBox = $boundingBox->extendedWithBoundingBox($curve->getBoundingBox());
×
160
        }
161

162
        return $boundingBox;
×
163
    }
164

165
    /**
166
     * @return list<list<list<float>>>
167
     */
168
    #[Override]
169
    public function toArray() : array
170
    {
171
        return array_map(
252✔
172
            fn (Curve $curve) => $curve->toArray(),
252✔
173
            $this->curves,
252✔
174
        );
252✔
175
    }
176

177
    #[Override]
178
    public function project(Projector $projector): static
179
    {
180
        return new CompoundCurve(
×
181
            $projector->getTargetCoordinateSystem($this->coordinateSystem),
×
182
            ...array_map(
×
183
                fn (Curve $curve) => $curve->project($projector),
×
184
                $this->curves,
×
185
            ),
×
186
        );
×
187
    }
188

189
    /**
190
     * Returns the number of curves in this CompoundCurve.
191
     */
192
    #[Override]
193
    public function count() : int
194
    {
195
        return count($this->curves);
455✔
196
    }
197

198
    /**
199
     * Returns an iterator for the curves in this CompoundCurve.
200
     *
201
     * @return ArrayIterator<int<0, max>, LineString|CircularString>
202
     */
203
    #[Override]
204
    public function getIterator() : ArrayIterator
205
    {
206
        return new ArrayIterator($this->curves);
1,036✔
207
    }
208

209
    /**
210
     * Returns a copy of this CompoundCurve, with the given curves added.
211
     */
212
    public function withAddedCurves(LineString|CircularString ...$curves): CompoundCurve
213
    {
214
        return new CompoundCurve($this->coordinateSystem, ...$this->curves, ...$curves);
56✔
215
    }
216
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc