Coverage Report

Created: 2025-06-09 08:44

/src/gdal/ogr/ogrmultipolygon.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  The OGRMultiPolygon class.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1999, Frank Warmerdam
9
 * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "cpl_port.h"
15
#include "ogr_geometry.h"
16
17
#include "ogr_api.h"
18
#include "ogr_core.h"
19
#include "ogr_p.h"
20
21
/************************************************************************/
22
/*              OGRMultiPolygon( const OGRMultiPolygon& )               */
23
/************************************************************************/
24
25
/**
26
 * \brief Copy constructor.
27
 *
28
 * Note: before GDAL 2.1, only the default implementation of the constructor
29
 * existed, which could be unsafe to use.
30
 *
31
 * @since GDAL 2.1
32
 */
33
34
27.9k
OGRMultiPolygon::OGRMultiPolygon(const OGRMultiPolygon &) = default;
35
36
/************************************************************************/
37
/*                  operator=( const OGRMultiPolygon&)                    */
38
/************************************************************************/
39
40
/**
41
 * \brief Assignment operator.
42
 *
43
 * Note: before GDAL 2.1, only the default implementation of the operator
44
 * existed, which could be unsafe to use.
45
 *
46
 * @since GDAL 2.1
47
 */
48
49
OGRMultiPolygon &OGRMultiPolygon::operator=(const OGRMultiPolygon &other)
50
0
{
51
0
    if (this != &other)
52
0
    {
53
0
        OGRMultiSurface::operator=(other);
54
0
    }
55
0
    return *this;
56
0
}
57
58
/************************************************************************/
59
/*                               clone()                                */
60
/************************************************************************/
61
62
OGRMultiPolygon *OGRMultiPolygon::clone() const
63
64
14.8k
{
65
14.8k
    auto ret = new (std::nothrow) OGRMultiPolygon(*this);
66
14.8k
    if (ret)
67
14.8k
    {
68
14.8k
        if (ret->WkbSize() != WkbSize())
69
0
        {
70
0
            delete ret;
71
0
            ret = nullptr;
72
0
        }
73
14.8k
    }
74
14.8k
    return ret;
75
14.8k
}
76
77
/************************************************************************/
78
/*                          getGeometryType()                           */
79
/************************************************************************/
80
81
OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const
82
83
374k
{
84
374k
    if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
85
18.8k
        return wkbMultiPolygonZM;
86
355k
    else if (flags & OGR_G_MEASURED)
87
9.15k
        return wkbMultiPolygonM;
88
346k
    else if (flags & OGR_G_3D)
89
100k
        return wkbMultiPolygon25D;
90
246k
    else
91
246k
        return wkbMultiPolygon;
92
374k
}
93
94
/************************************************************************/
95
/*                          getGeometryName()                           */
96
/************************************************************************/
97
98
const char *OGRMultiPolygon::getGeometryName() const
99
100
32.3k
{
101
32.3k
    return "MULTIPOLYGON";
102
32.3k
}
103
104
/************************************************************************/
105
/*                          isCompatibleSubType()                       */
106
/************************************************************************/
107
108
OGRBoolean
109
OGRMultiPolygon::isCompatibleSubType(OGRwkbGeometryType eGeomType) const
110
3.43M
{
111
3.43M
    return wkbFlatten(eGeomType) == wkbPolygon;
112
3.43M
}
113
114
/************************************************************************/
115
/*                           importFromWkb()                            */
116
/************************************************************************/
117
118
OGRErr OGRMultiPolygon::importFromWkb(const unsigned char *pabyData,
119
                                      size_t nSize, OGRwkbVariant eWkbVariant,
120
                                      size_t &nBytesConsumedOut)
121
122
8.69k
{
123
8.69k
    if (nGeomCount == 1 && nSize >= 9 && flags == 0 && pabyData[0] == wkbNDR &&
124
8.69k
        memcmp(pabyData + 1, "\x06\x00\x00\x00\x01\x00\x00\x00", 8) == 0)
125
0
    {
126
        // Optimization to import a Intel-ordered 1-part multipolyon on
127
        // top of an existing 1-part multipolygon, to save dynamic memory
128
        // allocations.
129
0
        const size_t nDataOffset = 9;
130
0
        size_t nBytesConsumedPolygon = 0;
131
        // cppcheck-suppress knownConditionTrueFalse
132
0
        if (nSize != static_cast<size_t>(-1))
133
0
            nSize -= nDataOffset;
134
0
        OGRErr eErr =
135
0
            cpl::down_cast<OGRPolygon *>(papoGeoms[0])
136
0
                ->OGRPolygon::importFromWkb(pabyData + nDataOffset, nSize,
137
0
                                            eWkbVariant, nBytesConsumedPolygon);
138
0
        if (eErr == OGRERR_NONE)
139
0
        {
140
0
            nBytesConsumedOut = nDataOffset + nBytesConsumedPolygon;
141
0
        }
142
0
        else
143
0
        {
144
0
            empty();
145
0
        }
146
0
        return eErr;
147
0
    }
148
149
8.69k
    return OGRGeometryCollection::importFromWkbInternal(
150
8.69k
        pabyData, nSize, /*nRecLevel=*/0, eWkbVariant, nBytesConsumedOut);
151
8.69k
}
152
153
/************************************************************************/
154
/*                            exportToWkt()                             */
155
/************************************************************************/
156
157
std::string OGRMultiPolygon::exportToWkt(const OGRWktOptions &opts,
158
                                         OGRErr *err) const
159
14.0k
{
160
14.0k
    return exportToWktInternal(opts, err, "POLYGON");
161
14.0k
}
162
163
/************************************************************************/
164
/*                         hasCurveGeometry()                           */
165
/************************************************************************/
166
167
OGRBoolean OGRMultiPolygon::hasCurveGeometry(int /* bLookForNonLinear */) const
168
17.7k
{
169
17.7k
    return FALSE;
170
17.7k
}
171
172
/************************************************************************/
173
/*                          CastToMultiSurface()                        */
174
/************************************************************************/
175
176
/**
177
 * \brief Cast to multisurface.
178
 *
179
 * The passed in geometry is consumed and a new one returned .
180
 *
181
 * @param poMP the input geometry - ownership is passed to the method.
182
 * @return new geometry.
183
 */
184
185
OGRMultiSurface *OGRMultiPolygon::CastToMultiSurface(OGRMultiPolygon *poMP)
186
0
{
187
0
    OGRMultiSurface *poMS = new OGRMultiSurface();
188
0
    TransferMembersAndDestroy(poMP, poMS);
189
0
    return poMS;
190
0
}
191
192
/************************************************************************/
193
/*               _addGeometryWithExpectedSubGeometryType()              */
194
/*      Only to be used in conjunction with OGRPolyhedralSurface.       */
195
/*                        DO NOT USE IT ELSEWHERE.                      */
196
/************************************************************************/
197
198
//! @cond Doxygen_Suppress
199
OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType(
200
    const OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType)
201
202
0
{
203
0
    OGRGeometry *poClone = poNewGeom->clone();
204
0
    OGRErr eErr;
205
206
0
    if (poClone == nullptr)
207
0
        return OGRERR_FAILURE;
208
0
    eErr = _addGeometryDirectlyWithExpectedSubGeometryType(poClone,
209
0
                                                           eSubGeometryType);
210
0
    if (eErr != OGRERR_NONE)
211
0
        delete poClone;
212
213
0
    return eErr;
214
0
}
215
216
//! @endcond
217
218
/************************************************************************/
219
/*                 _addGeometryDirectlyWithExpectedSubGeometryType()    */
220
/*      Only to be used in conjunction with OGRPolyhedralSurface.       */
221
/*                        DO NOT USE IT ELSEWHERE.                      */
222
/************************************************************************/
223
224
//! @cond Doxygen_Suppress
225
OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType(
226
    OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType)
227
14.2k
{
228
14.2k
    if (wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType)
229
0
        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
230
231
14.2k
    HomogenizeDimensionalityWith(poNewGeom);
232
233
14.2k
    OGRGeometry **papoNewGeoms = static_cast<OGRGeometry **>(
234
14.2k
        VSI_REALLOC_VERBOSE(papoGeoms, sizeof(void *) * (nGeomCount + 1)));
235
14.2k
    if (papoNewGeoms == nullptr)
236
0
        return OGRERR_FAILURE;
237
238
14.2k
    papoGeoms = papoNewGeoms;
239
14.2k
    papoGeoms[nGeomCount] = poNewGeom;
240
14.2k
    nGeomCount++;
241
242
14.2k
    return OGRERR_NONE;
243
14.2k
}
244
245
//! @endcond