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

brick / geo / 13715715561

06 Mar 2025 10:47PM UTC coverage: 44.086% (-40.4%) from 84.507%
13715715561

push

github

BenMorel
Remove Psalm-specific annotations

1543 of 3500 relevant lines covered (44.09%)

270.91 hits per line

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

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

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

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

49
        if (! $rings) {
494✔
50
            return;
228✔
51
        }
52

53
        CoordinateSystem::check($this, ...$rings);
270✔
54

55
        $this->rings = array_values($rings);
270✔
56
    }
57

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

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

84
        return $this->rings[0];
32✔
85
    }
86

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

96
        return count($this->rings) - 1;
10✔
97
    }
98

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

112
        return $this->rings[$n];
16✔
113
    }
114

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

125
    #[NoProxy, Override]
126
    public function geometryType() : string
127
    {
128
        return 'CurvePolygon';
192✔
129
    }
130

131
    #[NoProxy, Override]
132
    public function geometryTypeBinary() : int
133
    {
134
        return Geometry::CURVEPOLYGON;
100✔
135
    }
136

137
    #[Override]
138
    public function getBoundingBox() : BoundingBox
139
    {
140
        $boundingBox = BoundingBox::new();
×
141

142
        foreach ($this->rings as $ring) {
×
143
            $boundingBox = $boundingBox->extendedWithBoundingBox($ring->getBoundingBox());
×
144
        }
145

146
        return $boundingBox;
×
147
    }
148

149
    #[Override]
150
    public function toArray() : array
151
    {
152
        return array_map(
64✔
153
            fn (Curve $ring) => $ring->toArray(),
64✔
154
            $this->rings,
64✔
155
        );
64✔
156
    }
157

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

170
    /**
171
     * Returns the number of rings (exterior + interior) in this CurvePolygon.
172
     */
173
    #[Override]
174
    public function count() : int
175
    {
176
        return count($this->rings);
100✔
177
    }
178

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

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

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

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