Coverage Report

Created: 2025-11-24 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/geom/Surface.cpp
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2024 ISciences LLC
7
 * Copyright (C) 2011 Sandro Santilli <strk@kbt.io>
8
 * Copyright (C) 2005-2006 Refractions Research Inc.
9
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
10
 *
11
 * This is free software; you can redistribute and/or modify it under
12
 * the terms of the GNU Lesser General Public Licence as published
13
 * by the Free Software Foundation.
14
 * See the COPYING file for more information.
15
 *
16
 **********************************************************************
17
 *
18
 * Last port: geom/Polygon.java r320 (JTS-1.12)
19
 *
20
 **********************************************************************/
21
22
#include <geos/geom/Curve.h>
23
#include <geos/geom/GeometryFactory.h>
24
#include <geos/geom/Surface.h>
25
#include <geos/util.h>
26
27
namespace geos {
28
namespace geom {
29
30
void
31
Surface::apply_ro(CoordinateFilter* filter) const
32
0
{
33
0
    getExteriorRing()->apply_ro(filter);
34
0
    for (std::size_t i = 0; i < getNumInteriorRing(); i++) {
35
0
        getInteriorRingN(i)->apply_ro(filter);
36
0
    }
37
0
}
38
39
void
40
Surface::apply_ro(CoordinateSequenceFilter& filter) const
41
310k
{
42
310k
    getExteriorRing()->apply_ro(filter);
43
44
313k
    for (std::size_t i = 0; !filter.isDone() && i < getNumInteriorRing(); i++) {
45
3.26k
        getInteriorRingN(i)->apply_ro(filter);
46
3.26k
    }
47
310k
}
48
49
void
50
Surface::apply_ro(GeometryComponentFilter* filter) const
51
34.0k
{
52
34.0k
    filter->filter_ro(this);
53
34.0k
    getExteriorRing()->apply_ro(filter);
54
61.4k
    for (std::size_t i = 0; !filter->isDone() && i < getNumInteriorRing(); i++) {
55
27.3k
        getInteriorRingN(i)->apply_ro(filter);
56
27.3k
    }
57
34.0k
}
58
59
void
60
Surface::apply_ro(GeometryFilter* filter) const
61
11.8M
{
62
11.8M
    filter->filter_ro(this);
63
11.8M
}
64
65
void
66
Surface::apply_rw(const CoordinateFilter* filter)
67
2.63k
{
68
2.63k
    getExteriorRing()->apply_rw(filter);
69
3.07k
    for (std::size_t i = 0; i < getNumInteriorRing(); i++) {
70
442
        getInteriorRingN(i)->apply_rw(filter);
71
442
    }
72
2.63k
}
73
74
void
75
Surface::apply_rw(CoordinateSequenceFilter& filter)
76
0
{
77
0
    getExteriorRing()->apply_rw(filter);
78
79
0
    for (std::size_t i = 0; !filter.isDone() && i < getNumInteriorRing(); i++) {
80
0
        getInteriorRingN(i)->apply_rw(filter);
81
0
    }
82
83
0
    if (filter.isGeometryChanged()) {
84
0
        geometryChanged();
85
0
    }
86
0
}
87
88
void
89
Surface::apply_rw(GeometryComponentFilter* filter)
90
0
{
91
0
    filter->filter_rw(this);
92
0
    getExteriorRing()->apply_rw(filter);
93
0
    for (std::size_t i = 0; !filter->isDone() && i < getNumInteriorRing(); i++) {
94
0
        getInteriorRingN(i)->apply_rw(filter);
95
0
    }
96
0
}
97
98
void
99
Surface::apply_rw(GeometryFilter* filter)
100
0
{
101
0
    filter->filter_rw(this);
102
0
}
103
104
int
105
Surface::compareToSameClass(const Geometry* g) const
106
0
{
107
0
    const Surface* p = detail::down_cast<const Surface*>(g);
108
0
    int shellComp = getExteriorRing()->compareTo(p->getExteriorRing());
109
0
    if (shellComp != 0) {
110
0
        return shellComp;
111
0
    }
112
113
0
    size_t nHole1 = getNumInteriorRing();
114
0
    size_t nHole2 = p->getNumInteriorRing();
115
0
    if (nHole1 < nHole2) {
116
0
        return -1;
117
0
    }
118
0
    if (nHole1 > nHole2) {
119
0
        return 1;
120
0
    }
121
122
0
    for (size_t i=0; i < nHole1; i++) {
123
0
        const Curve* lr = p->getInteriorRingN(i);
124
0
        const int holeComp = getInteriorRingN(i)->compareTo(lr);
125
0
        if (holeComp != 0) {
126
0
            return holeComp;
127
0
        }
128
0
    }
129
130
0
    return 0;
131
0
}
132
133
std::unique_ptr<Geometry>
134
Surface::convexHull() const
135
0
{
136
0
    return getExteriorRing()->convexHull();
137
0
}
138
139
std::unique_ptr<Geometry>
140
Surface::createEmptyRing(const GeometryFactory& factory)
141
0
{
142
0
    return factory.createLinearRing();
143
0
}
144
145
bool
146
Surface::equalsExact(const Geometry* other, double tolerance) const
147
0
{
148
0
    if (!isEquivalentClass(other)) {
149
0
        return false;
150
0
    }
151
152
0
    const Surface* otherPolygon = detail::down_cast<const Surface*>(other);
153
0
    if (! otherPolygon) {
154
0
        return false;
155
0
    }
156
157
0
    if (!getExteriorRing()->equalsExact(otherPolygon->getExteriorRing(), tolerance)) {
158
0
        return false;
159
0
    }
160
161
0
    if (getNumInteriorRing() != otherPolygon->getNumInteriorRing()) {
162
0
        return false;
163
0
    }
164
165
0
    for (std::size_t i = 0; i < getNumInteriorRing(); i++) {
166
0
        const Curve* hole = getInteriorRingN(i);
167
0
        const Curve* otherhole = otherPolygon->getInteriorRingN(i);
168
0
        if (!hole->equalsExact(otherhole, tolerance)) {
169
0
            return false;
170
0
        }
171
0
    }
172
173
0
    return true;
174
0
}
175
176
bool
177
Surface::equalsIdentical(const Geometry* other_g) const
178
0
{
179
0
    if (!isEquivalentClass(other_g)) {
180
0
        return false;
181
0
    }
182
183
0
    const auto& other = static_cast<const Surface&>(*other_g);
184
185
0
    if (getNumInteriorRing() != other.getNumInteriorRing()) {
186
0
        return false;
187
0
    }
188
189
0
    if (!getExteriorRing()->equalsIdentical(other.getExteriorRing())) {
190
0
        return false;
191
0
    }
192
193
0
    for (std::size_t i = 0; i < getNumInteriorRing(); i++) {
194
0
        if (!getInteriorRingN(i)->equalsIdentical(other.getInteriorRingN(i))) {
195
0
            return false;
196
0
        }
197
0
    }
198
199
0
    return true;
200
0
}
201
202
const CoordinateXY*
203
Surface::getCoordinate() const
204
0
{
205
0
    return getExteriorRing()->getCoordinate();
206
0
}
207
208
uint8_t
209
Surface::getCoordinateDimension() const
210
55.5k
{
211
55.5k
    uint8_t dimension = 2;
212
213
55.5k
    if (getExteriorRing() != nullptr) {
214
55.5k
        dimension = std::max(dimension, getExteriorRing()->getCoordinateDimension());
215
55.5k
    }
216
217
115k
    for (std::size_t i = 0; i < getNumInteriorRing(); i++) {
218
59.7k
        dimension = std::max(dimension, getInteriorRingN(i)->getCoordinateDimension());
219
59.7k
    }
220
221
55.5k
    return dimension;
222
55.5k
}
223
224
const Envelope*
225
Surface::getEnvelopeInternal() const
226
10.1M
{
227
10.1M
    return getExteriorRing()->getEnvelopeInternal();
228
10.1M
}
229
230
double
231
Surface::getLength() const
232
0
{
233
0
    double len = 0.0;
234
0
    len += getExteriorRing()->getLength();
235
0
    for (std::size_t i = 0; i < getNumInteriorRing(); i++) {
236
0
        len += getInteriorRingN(i)->getLength();
237
0
    }
238
0
    return len;
239
0
}
240
241
size_t
242
Surface::getNumPoints() const
243
0
{
244
0
    std::size_t numPoints = getExteriorRing()->getNumPoints();
245
0
    for (std::size_t i = 0; i < getNumInteriorRing(); i++) {
246
0
        numPoints += getInteriorRingN(i)->getNumPoints();
247
0
    }
248
0
    return numPoints;
249
0
}
250
251
bool
252
Surface::hasM() const
253
3.02M
{
254
3.02M
    if (getExteriorRing()->hasM()) {
255
6.28k
        return true;
256
6.28k
    }
257
3.89M
    for (std::size_t i = 0 ; i < getNumInteriorRing(); i++) {
258
875k
        if (getInteriorRingN(i)->hasM()) {
259
17
            return true;
260
17
        }
261
875k
    }
262
3.01M
    return false;
263
3.01M
}
264
265
bool
266
Surface::hasZ() const
267
3.02M
{
268
3.02M
    if (getExteriorRing()->hasZ()) {
269
4.20k
        return true;
270
4.20k
    }
271
4.25M
    for (std::size_t i = 0 ; i < getNumInteriorRing(); i++) {
272
1.23M
        if (getInteriorRingN(i)->hasZ()) {
273
10
            return true;
274
10
        }
275
1.23M
    }
276
3.02M
    return false;
277
3.02M
}
278
279
bool
280
Surface::isEmpty() const
281
8.21M
{
282
8.21M
    return getExteriorRing()->isEmpty();
283
8.21M
}
284
285
}
286
}