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

brick / geo / 13766209603

09 Mar 2025 10:35PM UTC coverage: 87.414% (+3.3%) from 84.117%
13766209603

push

github

BenMorel
Add Point::isEqualTo() (WIP: finish? keep?)

8 of 8 new or added lines in 2 files covered. (100.0%)

73 existing lines in 16 files now uncovered.

1653 of 1891 relevant lines covered (87.41%)

1946.79 hits per line

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

67.5
/src/CurvePolygon.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\NoSuchGeometryException;
11
use Brick\Geo\Projector\Projector;
12
use Override;
13

14
/**
15
 * A CurvePolygon is a planar Surface defined by 1 exterior boundary and 0 or more interior boundaries.
16
 *
17
 * A CurvePolygon instance differs from a Polygon instance in that a CurvePolygon instance may contain
18
 * the following circular arc segments: CircularString and CompoundCurve in addition to LineString.
19
 *
20
 * @template-implements \IteratorAggregate<int<0, max>, Curve>
21
 */
22
final readonly class CurvePolygon extends Surface implements \Countable, \IteratorAggregate
23
{
24
    /**
25
     * The rings that compose this CurvePolygon.
26
     *
27
     * The first one represents the exterior ring, and the
28
     * (optional) other ones represent the interior rings (holes) of the CurvePolygon.
29
     *
30
     * An empty CurvePolygon contains no rings.
31
     *
32
     * @var list<Curve>
33
     */
34
    public array $rings;
35

36
    /**
37
     * The coordinate system of each of the rings must match the one of the CurvePolygon.
38
     *
39
     * @param CoordinateSystem $cs       The coordinate system of the CurvePolygon.
40
     * @param Curve            ...$rings The rings that compose the CurvePolygon.
41
     *
42
     * @throws CoordinateSystemException If different coordinate systems are used.
43
     */
44
    public function __construct(CoordinateSystem $cs, Curve ...$rings)
45
    {
46
        $isEmpty = (count($rings) === 0);
1,841✔
47
        parent::__construct($cs, $isEmpty);
1,841✔
48

49
        $this->rings = array_values($rings);
1,841✔
50

51
        if ($isEmpty) {
1,841✔
52
            return;
854✔
53
        }
54

55
        CoordinateSystem::check($this, ...$rings);
1,001✔
56
    }
57

58
    /**
59
     * Creates a non-empty CurvePolygon composed of the given rings.
60
     *
61
     * @param Curve    $exteriorRing  The exterior ring.
62
     * @param Curve ...$interiorRings The interior rings, if any.
63
     *
64
     * @throws CoordinateSystemException If the rings use different coordinate systems.
65
     */
66
    public static function of(Curve $exteriorRing, Curve ...$interiorRings) : CurvePolygon
67
    {
68
        return new CurvePolygon($exteriorRing->coordinateSystem, $exteriorRing, ...$interiorRings);
×
69
    }
70

71
    /**
72
     * Returns the exterior ring of this CurvePolygon.
73
     *
74
     * @throws EmptyGeometryException
75
     */
76
    public function exteriorRing() : Curve
77
    {
78
        if ($this->isEmpty) {
140✔
79
            throw new EmptyGeometryException('An empty CurvePolygon has no exterior ring.');
28✔
80
        }
81

82
        return $this->rings[0];
112✔
83
    }
84

85
    /**
86
     * Returns the number of interior rings in this CurvePolygon.
87
     */
88
    public function numInteriorRings() : int
89
    {
90
        if ($this->isEmpty) {
63✔
91
            return 0;
28✔
92
        }
93

94
        return count($this->rings) - 1;
35✔
95
    }
96

97
    /**
98
     * Returns the specified interior ring N in this CurvePolygon.
99
     *
100
     * @param int $n The ring number, 1-based.
101
     *
102
     * @throws NoSuchGeometryException If there is no interior ring at this index.
103
     */
104
    public function interiorRingN(int $n) : Curve
105
    {
106
        if ($n === 0 || ! isset($this->rings[$n])) {
308✔
107
            throw new NoSuchGeometryException('There is no interior ring in this CurvePolygon at index ' . $n);
252✔
108
        }
109

110
        return $this->rings[$n];
56✔
111
    }
112

113
    /**
114
     * Returns the interior rings in this CurvePolygon.
115
     *
116
     * @return list<Curve>
117
     */
118
    public function interiorRings() : array
119
    {
120
        return array_slice($this->rings, 1);
70✔
121
    }
122

123
    #[Override]
124
    public function geometryType() : string
125
    {
126
        return 'CurvePolygon';
784✔
127
    }
128

129
    #[Override]
130
    public function geometryTypeBinary() : int
131
    {
132
        return Geometry::CURVEPOLYGON;
350✔
133
    }
134

135
    #[Override]
136
    public function getBoundingBox() : BoundingBox
137
    {
138
        return array_reduce(
×
UNCOV
139
            $this->rings,
×
140
            fn (BoundingBox $boundingBox, Curve $ring) => $boundingBox->extendedWithBoundingBox($ring->getBoundingBox()),
×
141
            BoundingBox::new(),
×
UNCOV
142
        );
×
143
    }
144

145
    #[Override]
146
    public function toArray() : array
147
    {
148
        return array_map(
224✔
149
            fn (Curve $ring) => $ring->toArray(),
224✔
150
            $this->rings,
224✔
151
        );
224✔
152
    }
153

154
    #[Override]
155
    public function project(Projector $projector): static
156
    {
UNCOV
157
        return new CurvePolygon(
×
UNCOV
158
            $projector->getTargetCoordinateSystem($this->coordinateSystem),
×
159
            ...array_map(
×
160
                fn (Curve $ring) => $ring->project($projector),
×
161
                $this->rings,
×
162
            ),
×
163
        );
×
164
    }
165

166
    /**
167
     * Returns the number of rings (exterior + interior) in this CurvePolygon.
168
     */
169
    #[Override]
170
    public function count() : int
171
    {
172
        return count($this->rings);
350✔
173
    }
174

175
    /**
176
     * Returns an iterator for the rings (exterior + interior) in this CurvePolygon.
177
     *
178
     * @return ArrayIterator<int<0, max>, Curve>
179
     */
180
    #[Override]
181
    public function getIterator() : ArrayIterator
182
    {
183
        return new ArrayIterator($this->rings);
798✔
184
    }
185

186
    /**
187
     * Returns a copy of this CurvePolygon, with the exterior ring replaced with the given one.
188
     */
189
    public function withExteriorRing(Curve $exteriorRing) : CurvePolygon
190
    {
191
        return new CurvePolygon($this->coordinateSystem, $exteriorRing, ...$this->interiorRings());
28✔
192
    }
193

194
    /**
195
     * Returns a copy of this CurvePolygon, with the interior rings replaced with the given ones.
196
     */
197
    public function withInteriorRings(Curve ...$interiorRings) : CurvePolygon
198
    {
199
        return new CurvePolygon($this->coordinateSystem, $this->exteriorRing(), ...$interiorRings);
42✔
200
    }
201

202
    /**
203
     * Returns a copy of this CurvePolygon, with the given interior rings added.
204
     */
205
    public function withAddedInteriorRings(Curve ...$interiorRings) : CurvePolygon
206
    {
207
        return new CurvePolygon($this->coordinateSystem, $this->exteriorRing(), ...$this->interiorRings(), ...$interiorRings);
42✔
208
    }
209
}
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