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

brick / geo / 13633473181

03 Mar 2025 02:25PM UTC coverage: 83.61% (+0.2%) from 83.425%
13633473181

push

github

BenMorel
BoundingBox: readonly + promoted properties

21 of 28 new or added lines in 10 files covered. (75.0%)

41 existing lines in 5 files now uncovered.

1561 of 1867 relevant lines covered (83.61%)

1882.91 hits per line

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

61.29
/src/PolyhedralSurface.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\NoSuchGeometryException;
10
use Brick\Geo\Projector\Projector;
11
use Override;
12

13
/**
14
 * A PolyhedralSurface is a contiguous collection of polygons, which share common boundary segments.
15
 *
16
 * For each pair of polygons that "touch", the common boundary shall be expressible as a finite collection
17
 * of LineStrings. Each such LineString shall be part of the boundary of at most 2 Polygon patches.
18
 *
19
 * For any two polygons that share a common boundary, the "top" of the polygon shall be consistent. This means
20
 * that when two linear rings from these two Polygons traverse the common boundary segment, they do so in
21
 * opposite directions. Since the Polyhedral surface is contiguous, all polygons will be thus consistently oriented.
22
 * This means that a non-oriented surface (such as Möbius band) shall not have single surface representations.
23
 * They may be represented by a MultiSurface.
24
 *
25
 * If each such LineString is the boundary of exactly 2 Polygon patches, then the PolyhedralSurface is a simple,
26
 * closed polyhedron and is topologically isomorphic to the surface of a sphere. By the Jordan Surface Theorem
27
 * (Jordan’s Theorem for 2-spheres), such polyhedrons enclose a solid topologically isomorphic to the interior of a
28
 * sphere; the ball. In this case, the "top" of the surface will either point inward or outward of the enclosed
29
 * finite solid. If outward, the surface is the exterior boundary of the enclosed surface. If inward, the surface
30
 * is the interior of the infinite complement of the enclosed solid. A Ball with some number of voids (holes) inside
31
 * can thus be presented as one exterior boundary shell, and some number in interior boundary shells.
32
 */
33
class PolyhedralSurface extends Surface
34
{
35
    /**
36
     * The polygons that compose this PolyhedralSurface.
37
     *
38
     * An empty PolyhedralSurface contains no polygons.
39
     *
40
     * @psalm-var list<Polygon>
41
     *
42
     * @var Polygon[]
43
     */
44
    protected array $patches = [];
45

46
    /**
47
     * The coordinate system of each of the patches must match the one of the PolyhedralSurface.
48
     *
49
     * @param CoordinateSystem $cs         The coordinate system of the PolyhedralSurface.
50
     * @param Polygon          ...$patches The patches that compose the PolyhedralSurface.
51
     *
52
     * @throws CoordinateSystemException If different coordinate systems are used.
53
     */
54
    public function __construct(CoordinateSystem $cs, Polygon ...$patches)
55
    {
56
        parent::__construct($cs, ! $patches);
3,094✔
57

58
        if (! $patches) {
3,094✔
59
            return;
1,498✔
60
        }
61

62
        CoordinateSystem::check($this, ...$patches);
1,624✔
63

64
        $this->patches = array_values($patches);
1,624✔
65
    }
66

67
    /**
68
     * Creates a non-empty PolyhedralSurface composed of the given patches.
69
     *
70
     * @psalm-suppress UnsafeInstantiation
71
     *
72
     * @param Polygon    $patch1 The first patch.
73
     * @param Polygon ...$patchN The subsequent patches, if any.
74
     *
75
     * @throws CoordinateSystemException If the patches use different coordinate systems.
76
     */
77
    public static function of(Polygon $patch1, Polygon ...$patchN) : PolyhedralSurface
78
    {
79
        return new static($patch1->coordinateSystem(), $patch1, ...$patchN);
7✔
80
    }
81

82
    public function numPatches() : int
83
    {
84
        return count($this->patches);
56✔
85
    }
86

87
    /**
88
     * Returns the specified patch N in this PolyhedralSurface.
89
     *
90
     * @param int $n The patch number, 1-based.
91
     *
92
     * @throws NoSuchGeometryException If there is no patch at this index.
93
     */
94
    public function patchN(int $n) : Polygon
95
    {
96
        if (! isset($this->patches[$n - 1])) {
343✔
97
            throw new NoSuchGeometryException('There is no patch in this PolyhedralSurface at index ' . $n);
224✔
98
        }
99

100
        return $this->patches[$n - 1];
119✔
101
    }
102

103
    /**
104
     * Returns the patches that compose this PolyhedralSurface.
105
     *
106
     * @psalm-return list<Polygon>
107
     *
108
     * @return Polygon[]
109
     */
110
    public function patches() : array
111
    {
112
        return $this->patches;
×
113
    }
114

115
    #[Override]
116
    public function geometryType() : string
117
    {
118
        return 'PolyhedralSurface';
798✔
119
    }
120

121
    #[Override]
122
    public function geometryTypeBinary() : int
123
    {
124
        return Geometry::POLYHEDRALSURFACE;
343✔
125
    }
126

127
    #[Override]
128
    public function getBoundingBox() : BoundingBox
129
    {
NEW
130
        $boundingBox = BoundingBox::new();
×
131

132
        foreach ($this->patches as $patch) {
×
133
            $boundingBox = $boundingBox->extendedWithBoundingBox($patch->getBoundingBox());
×
134
        }
135

136
        return $boundingBox;
×
137
    }
138

139
    #[Override]
140
    public function toArray() : array
141
    {
142
        $result = [];
448✔
143

144
        foreach ($this->patches as $patch) {
448✔
145
            $result[] = $patch->toArray();
224✔
146
        }
147

148
        return $result;
448✔
149
    }
150

151
    #[Override]
152
    public function project(Projector $projector): PolyhedralSurface
153
    {
154
        return new PolyhedralSurface(
×
155
            $projector->getTargetCoordinateSystem($this->coordinateSystem),
×
156
            ...array_map(
×
157
                fn (Polygon $patch) => $patch->project($projector),
×
158
                $this->patches,
×
159
            ),
×
160
        );
×
161
    }
162

163
    /**
164
     * Returns the number of patches in this PolyhedralSurface.
165
     *
166
     * Required by interface Countable.
167
     */
168
    #[Override]
169
    public function count() : int
170
    {
171
        return count($this->patches);
686✔
172
    }
173

174
    /**
175
     * Returns an iterator for the patches in this PolyhedralSurface.
176
     *
177
     * Required by interface IteratorAggregate.
178
     *
179
     * @psalm-return ArrayIterator<int, Polygon>
180
     */
181
    #[Override]
182
    public function getIterator() : ArrayIterator
183
    {
184
        return new ArrayIterator($this->patches);
1,491✔
185
    }
186

187
    /**
188
     * Returns a copy of this PolyhedralSurface, with the given patches added.
189
     *
190
     * @psalm-suppress UnsafeInstantiation
191
     */
192
    public function withAddedPatches(Polygon ...$patches) : PolyhedralSurface
193
    {
194
        return new static($this->coordinateSystem, ...$this->patches, ...$patches);
105✔
195
    }
196
}
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