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

brick / geo / 13753277563

09 Mar 2025 10:43PM UTC coverage: 49.787% (+2.5%) from 47.295%
13753277563

push

github

BenMorel
Prepare for release

1749 of 3513 relevant lines covered (49.79%)

975.53 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\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 Override;
15

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

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

52
        if (! $points) {
12,675✔
53
            return;
919✔
54
        }
55

56
        CoordinateSystem::check($this, ...$points);
11,769✔
57

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

62
        $this->points = array_values($points);
11,762✔
63
    }
64

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

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

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

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

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

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

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

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

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

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

126
        return $this->points[0];
525✔
127
    }
128

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

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

138
        return $this->points[$count - 1];
861✔
139
    }
140

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

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

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

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

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

181
    #[NoProxy, Override]
182
    public function geometryTypeBinary() : int
183
    {
184
        return Geometry::LINESTRING;
2,105✔
185
    }
186

187
    #[Override]
188
    public function getBoundingBox() : BoundingBox
189
    {
190
        return array_reduce(
7✔
191
            $this->points,
7✔
192
            fn (BoundingBox $boundingBox, Point $point) => $boundingBox->extendedWithPoint($point),
7✔
193
            BoundingBox::new()
7✔
194
        );
7✔
195
    }
196

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

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

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

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

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