• 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

92.73
/src/LineString.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 LineString is a Curve with linear interpolation between Points.
17
 *
18
 * Each consecutive pair of Points defines a line segment.
19
 *
20
 * @template-implements \IteratorAggregate<Point>
21
 */
22
final class LineString extends Curve implements \Countable, \IteratorAggregate
23
{
24
    /**
25
     * The Points that compose this LineString.
26
     *
27
     * An empty LineString contains no points.
28
     * A non-empty LineString contains a minimum of 2 points.
29
     *
30
     * @var list<Point>
31
     */
32
    protected array $points = [];
33

34
    /**
35
     * A LineString must be composed of 2 points or more, or 0 points for an empty LineString.
36
     * A LineString with exactly 1 point is not allowed.
37
     *
38
     * The coordinate system of each of the points must match the one of the LineString.
39
     *
40
     * @param CoordinateSystem $cs        The coordinate system of the LineString.
41
     * @param Point            ...$points The points that compose the LineString.
42
     *
43
     * @throws InvalidGeometryException  If only one point was given.
44
     * @throws CoordinateSystemException If different coordinate systems are used.
45
     */
46
    public function __construct(CoordinateSystem $cs, Point ...$points)
47
    {
48
        parent::__construct($cs, ! $points);
13,030✔
49

50
        if (! $points) {
13,030✔
51
            return;
969✔
52
        }
53

54
        CoordinateSystem::check($this, ...$points);
12,074✔
55

56
        if (count($points) < 2) {
12,074✔
57
            throw new InvalidGeometryException('A LineString must be composed of at least 2 points.');
7✔
58
        }
59

60
        $this->points = array_values($points);
12,067✔
61
    }
62

63
    /**
64
     * Creates a non-empty LineString composed of the given points.
65
     *
66
     * @param Point    $point1 The first point.
67
     * @param Point ...$pointN The subsequent points.
68
     *
69
     * @throws InvalidGeometryException  If only one point was given.
70
     * @throws CoordinateSystemException If the points use different coordinate systems.
71
     */
72
    public static function of(Point $point1, Point ...$pointN) : LineString
73
    {
74
        return new LineString($point1->coordinateSystem(), $point1, ...$pointN);
×
75
    }
76

77
    /**
78
     * Creates a rectangle out of two 2D corner points.
79
     *
80
     * The result is a linear ring (closed and simple).
81
     *
82
     * @psalm-suppress PossiblyNullArgument
83
     *
84
     * @throws EmptyGeometryException    If any of the points is empty.
85
     * @throws CoordinateSystemException If the points use different coordinate systems, or are not 2D.
86
     */
87
    public static function rectangle(Point $a, Point $b) : LineString
88
    {
89
        $cs = $a->coordinateSystem();
49✔
90

91
        if (! $cs->isEqualTo($b->coordinateSystem())) {
49✔
92
            throw CoordinateSystemException::dimensionalityMix($cs, $b->coordinateSystem());
28✔
93
        }
94

95
        if ($cs->coordinateDimension() !== 2) {
21✔
96
            throw new CoordinateSystemException(__METHOD__ . ' expects 2D points.');
×
97
        }
98

99
        if ($a->isEmpty() || $b->isEmpty()) {
21✔
100
            throw new EmptyGeometryException('Points cannot be empty.');
×
101
        }
102

103
        $x1 = min($a->x(), $b->x());
21✔
104
        $x2 = max($a->x(), $b->x());
21✔
105

106
        $y1 = min($a->y(), $b->y());
21✔
107
        $y2 = max($a->y(), $b->y());
21✔
108

109
        $p1 = new Point($cs, $x1, $y1);
21✔
110
        $p2 = new Point($cs, $x2, $y1);
21✔
111
        $p3 = new Point($cs, $x2, $y2);
21✔
112
        $p4 = new Point($cs, $x1, $y2);
21✔
113

114
        return new LineString($cs, $p1, $p2, $p3, $p4, $p1);
21✔
115
    }
116

117
    #[Override]
118
    public function startPoint() : Point
119
    {
120
        if ($this->points === []) {
574✔
121
            throw new EmptyGeometryException('The LineString is empty and has no start point.');
28✔
122
        }
123

124
        return $this->points[0];
546✔
125
    }
126

127
    #[Override]
128
    public function endPoint() : Point
129
    {
130
        if ($this->points === []) {
924✔
131
            throw new EmptyGeometryException('The LineString is empty and has no end point.');
28✔
132
        }
133

134
        return end($this->points);
896✔
135
    }
136

137
    /**
138
     * Returns the number of Points in this LineString.
139
     */
140
    public function numPoints() : int
141
    {
142
        return count($this->points);
1,393✔
143
    }
144

145
    /**
146
     * Returns the specified Point N in this LineString.
147
     *
148
     * @param int $n The point number, 1-based.
149
     *
150
     * @throws NoSuchGeometryException If there is no Point at this index.
151
     */
152
    public function pointN(int $n) : Point
153
    {
154
        if (! isset($this->points[$n - 1])) {
154✔
155
            throw new NoSuchGeometryException('There is no Point in this LineString at index ' . $n);
56✔
156
        }
157

158
        return $this->points[$n - 1];
98✔
159
    }
160

161
    /**
162
     * Returns the points that compose this LineString.
163
     *
164
     * @return list<Point>
165
     */
166
    public function points() : array
167
    {
168
        return $this->points;
×
169
    }
170

171
    #[Override]
172
    public function geometryType() : string
173
    {
174
        return 'LineString';
1,820✔
175
    }
176

177
    #[Override]
178
    public function geometryTypeBinary() : int
179
    {
180
        return Geometry::LINESTRING;
1,764✔
181
    }
182

183
    #[Override]
184
    public function getBoundingBox() : BoundingBox
185
    {
186
        $boundingBox = BoundingBox::new();
7✔
187

188
        foreach ($this->points as $point) {
7✔
189
            $boundingBox = $boundingBox->extendedWithPoint($point);
7✔
190
        }
191

192
        return $boundingBox;
7✔
193
    }
194

195
    /**
196
     * @return list<list<float>>
197
     */
198
    #[Override]
199
    public function toArray() : array
200
    {
201
        return array_map(
2,198✔
202
            fn (Point $point) => $point->toArray(),
2,198✔
203
            $this->points,
2,198✔
204
        );
2,198✔
205
    }
206

207
    #[Override]
208
    public function project(Projector $projector): static
209
    {
210
        return new LineString(
140✔
211
            $projector->getTargetCoordinateSystem($this->coordinateSystem),
140✔
212
            ...array_map(
140✔
213
                fn (Point $point) => $point->project($projector),
140✔
214
                $this->points,
140✔
215
            ),
140✔
216
        );
140✔
217
    }
218

219
    /**
220
     * Returns the number of points in this LineString.
221
     */
222
    #[Override]
223
    public function count() : int
224
    {
225
        return count($this->points);
3,376✔
226
    }
227

228
    /**
229
     * Returns an iterator for the points in this LineString.
230
     *
231
     * @return ArrayIterator<int<0, max>, Point>
232
     */
233
    #[Override]
234
    public function getIterator() : ArrayIterator
235
    {
236
        return new ArrayIterator($this->points);
8,982✔
237
    }
238

239
    /**
240
     * Returns a copy of this LineString, with the given points added.
241
     */
242
    public function withAddedPoints(Point ...$points): LineString
243
    {
244
        return new LineString($this->coordinateSystem, ...$this->points, ...$points);
35✔
245
    }
246
}
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