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

brick / geo / 13715719367

06 Mar 2025 02:18PM UTC coverage: 84.117%. First build
13715719367

push

github

BenMorel
Public properties

71 of 77 new or added lines in 23 files covered. (92.21%)

1557 of 1851 relevant lines covered (84.12%)

1887.21 hits per line

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

92.98
/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 readonly 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
    public 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
        $isEmpty = (count($points) === 0);
13,030✔
49
        parent::__construct($cs, $isEmpty);
13,030✔
50

51
        $this->points = array_values($points);
13,030✔
52

53
        if ($isEmpty) {
13,030✔
54
            return;
969✔
55
        }
56

57
        CoordinateSystem::check($this, ...$points);
12,074✔
58

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

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

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

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

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

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

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

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

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

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

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

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

128
    #[Override]
129
    public function endPoint() : Point
130
    {
131
        $count = count($this->points);
924✔
132

133
        if ($count === 0) {
924✔
134
            throw new EmptyGeometryException('The LineString is empty and has no end point.');
28✔
135
        }
136

137
        return $this->points[$count - 1];
896✔
138
    }
139

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

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

161
        return $this->points[$n - 1];
98✔
162
    }
163

164
    /**
165
     * Returns the points that compose this LineString.
166
     *
167
     * @return list<Point>
168
     *
169
     * @deprecated Use $points property instead.
170
     */
171
    public function points() : array
172
    {
173
        return $this->points;
×
174
    }
175

176
    #[Override]
177
    public function geometryType() : string
178
    {
179
        return 'LineString';
1,820✔
180
    }
181

182
    #[Override]
183
    public function geometryTypeBinary() : int
184
    {
185
        return Geometry::LINESTRING;
1,764✔
186
    }
187

188
    #[Override]
189
    public function getBoundingBox() : BoundingBox
190
    {
191
        $boundingBox = BoundingBox::new();
7✔
192

193
        foreach ($this->points as $point) {
7✔
194
            $boundingBox = $boundingBox->extendedWithPoint($point);
7✔
195
        }
196

197
        return $boundingBox;
7✔
198
    }
199

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

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

224
    /**
225
     * Returns the number of points in this LineString.
226
     */
227
    #[Override]
228
    public function count() : int
229
    {
230
        return count($this->points);
3,376✔
231
    }
232

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

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