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

brick / geo / 17456208570

04 Sep 2025 07:10AM UTC coverage: 50.432%. Remained the same
17456208570

push

github

BenMorel
Use @extends and @implements instead of @template-* variants

For consistency with the rest of the project.

1867 of 3702 relevant lines covered (50.43%)

1140.21 hits per line

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

68.18
/src/CircularString.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo;
6

7
use ArrayIterator;
8
use Brick\Geo\Attribute\NoProxy;
9
use Brick\Geo\Exception\CoordinateSystemException;
10
use Brick\Geo\Exception\EmptyGeometryException;
11
use Brick\Geo\Exception\InvalidGeometryException;
12
use Brick\Geo\Exception\NoSuchGeometryException;
13
use Brick\Geo\Projector\Projector;
14
use Countable;
15
use IteratorAggregate;
16
use Override;
17

18
use function array_map;
19
use function array_reduce;
20
use function array_values;
21
use function count;
22

23
/**
24
 * A CircularString is a Curve made of zero or more connected circular arc segments.
25
 *
26
 * A circular arc segment is a curved segment defined by three points in a two-dimensional plane;
27
 * the first point cannot be the same as the third point.
28
 *
29
 * @implements IteratorAggregate<int<0, max>, Point>
30
 *
31
 * @final
32
 */
33
class CircularString extends Curve implements Countable, IteratorAggregate
34
{
35
    /**
36
     * The Points that compose this CircularString.
37
     *
38
     * An empty CircularString contains no points.
39
     *
40
     * @var list<Point>
41
     */
42
    protected array $points = [];
43

44
    /**
45
     * @throws InvalidGeometryException  If the number of points is invalid.
46
     * @throws CoordinateSystemException If different coordinate systems are used.
47
     */
48
    public function __construct(CoordinateSystem $cs, Point ...$points)
49
    {
50
        parent::__construct($cs, ! $points);
4,001✔
51

52
        if (! $points) {
4,001✔
53
            return;
856✔
54
        }
55

56
        CoordinateSystem::check($this, ...$points);
3,161✔
57

58
        $numPoints = count($points);
3,161✔
59

60
        if ($numPoints < 3) {
3,161✔
61
            throw new InvalidGeometryException('A CircularString must be made of at least 3 points.');
24✔
62
        }
63

64
        if ($numPoints % 2 === 0) {
3,137✔
65
            throw new InvalidGeometryException('A CircularString must have an odd number of points.');
16✔
66
        }
67

68
        $this->points = array_values($points);
3,121✔
69
    }
70

71
    /**
72
     * Creates a non-empty CircularString composed of the given points.
73
     *
74
     * @param Point $point1    The first point.
75
     * @param Point ...$pointN The subsequent points.
76
     *
77
     * @throws InvalidGeometryException  If the number of points is invalid.
78
     * @throws CoordinateSystemException If the points use different coordinate systems.
79
     */
80
    public static function of(Point $point1, Point ...$pointN): CircularString
81
    {
82
        return new CircularString($point1->coordinateSystem(), $point1, ...$pointN);
×
83
    }
84

85
    #[Override]
86
    public function startPoint(): Point
87
    {
88
        if (count($this->points) === 0) {
1,128✔
89
            throw new EmptyGeometryException('The CircularString is empty and has no start point.');
64✔
90
        }
91

92
        return $this->points[0];
1,064✔
93
    }
94

95
    #[Override]
96
    public function endPoint(): Point
97
    {
98
        $count = count($this->points);
712✔
99

100
        if ($count === 0) {
712✔
101
            throw new EmptyGeometryException('The CircularString is empty and has no end point.');
64✔
102
        }
103

104
        return $this->points[$count - 1];
648✔
105
    }
106

107
    /**
108
     * Returns the number of Points in this CircularString.
109
     */
110
    public function numPoints(): int
111
    {
112
        return count($this->points);
64✔
113
    }
114

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

128
        return $this->points[$n - 1];
104✔
129
    }
130

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

141
    #[NoProxy, Override]
142
    public function geometryType(): string
143
    {
144
        return 'CircularString';
1,751✔
145
    }
146

147
    #[NoProxy, Override]
148
    public function geometryTypeBinary(): int
149
    {
150
        return Geometry::CIRCULARSTRING;
839✔
151
    }
152

153
    #[Override]
154
    public function getBoundingBox(): BoundingBox
155
    {
156
        return array_reduce(
×
157
            $this->points,
×
158
            fn (BoundingBox $boundingBox, Point $point) => $boundingBox->extendedWithPoint($point),
×
159
            BoundingBox::new(),
×
160
        );
×
161
    }
162

163
    /**
164
     * @return list<list<float>>
165
     */
166
    #[Override]
167
    public function toArray(): array
168
    {
169
        return array_map(
512✔
170
            fn (Point $point) => $point->toArray(),
512✔
171
            $this->points,
512✔
172
        );
512✔
173
    }
174

175
    #[Override]
176
    public function project(Projector $projector): CircularString
177
    {
178
        return new CircularString(
×
179
            $projector->getTargetCoordinateSystem($this->coordinateSystem),
×
180
            ...array_map(
×
181
                fn (Point $point) => $point->project($projector),
×
182
                $this->points,
×
183
            ),
×
184
        );
×
185
    }
186

187
    /**
188
     * Returns the number of points in this CircularString.
189
     */
190
    #[Override]
191
    public function count(): int
192
    {
193
        return count($this->points);
847✔
194
    }
195

196
    /**
197
     * Returns an iterator for the points in this CircularString.
198
     *
199
     * @return ArrayIterator<int<0, max>, Point>
200
     */
201
    #[Override]
202
    public function getIterator(): ArrayIterator
203
    {
204
        return new ArrayIterator($this->points);
2,244✔
205
    }
206

207
    /**
208
     * Returns a copy of this CircularString, with the given points added.
209
     */
210
    public function withAddedPoints(Point ...$points): CircularString
211
    {
212
        return new CircularString($this->coordinateSystem, ...$this->points, ...$points);
48✔
213
    }
214
}
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