Coverage Report

Created: 2025-11-16 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrmultipolygon.cpp
Line
Count
Source
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
29
0
OGRMultiPolygon::OGRMultiPolygon(const OGRMultiPolygon &) = default;
30
31
/************************************************************************/
32
/*                  operator=( const OGRMultiPolygon&)                    */
33
/************************************************************************/
34
35
/**
36
 * \brief Assignment operator.
37
 */
38
39
OGRMultiPolygon &OGRMultiPolygon::operator=(const OGRMultiPolygon &other)
40
0
{
41
0
    if (this != &other)
42
0
    {
43
0
        OGRMultiSurface::operator=(other);
44
0
    }
45
0
    return *this;
46
0
}
47
48
/************************************************************************/
49
/*                               clone()                                */
50
/************************************************************************/
51
52
OGRMultiPolygon *OGRMultiPolygon::clone() const
53
54
0
{
55
0
    auto ret = new (std::nothrow) OGRMultiPolygon(*this);
56
0
    if (ret)
57
0
    {
58
0
        if (ret->WkbSize() != WkbSize())
59
0
        {
60
0
            delete ret;
61
0
            ret = nullptr;
62
0
        }
63
0
    }
64
0
    return ret;
65
0
}
66
67
/************************************************************************/
68
/*                          getGeometryType()                           */
69
/************************************************************************/
70
71
OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const
72
73
5.26k
{
74
5.26k
    if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
75
4.06k
        return wkbMultiPolygonZM;
76
1.19k
    else if (flags & OGR_G_MEASURED)
77
474
        return wkbMultiPolygonM;
78
724
    else if (flags & OGR_G_3D)
79
670
        return wkbMultiPolygon25D;
80
54
    else
81
54
        return wkbMultiPolygon;
82
5.26k
}
83
84
/************************************************************************/
85
/*                          getGeometryName()                           */
86
/************************************************************************/
87
88
const char *OGRMultiPolygon::getGeometryName() const
89
90
526
{
91
526
    return "MULTIPOLYGON";
92
526
}
93
94
/************************************************************************/
95
/*                          isCompatibleSubType()                       */
96
/************************************************************************/
97
98
OGRBoolean
99
OGRMultiPolygon::isCompatibleSubType(OGRwkbGeometryType eGeomType) const
100
1.91k
{
101
1.91k
    return wkbFlatten(eGeomType) == wkbPolygon;
102
1.91k
}
103
104
/************************************************************************/
105
/*                           importFromWkb()                            */
106
/************************************************************************/
107
108
OGRErr OGRMultiPolygon::importFromWkb(const unsigned char *pabyData,
109
                                      size_t nSize, OGRwkbVariant eWkbVariant,
110
                                      size_t &nBytesConsumedOut)
111
112
0
{
113
0
    if (nGeomCount == 1 && nSize >= 9 && flags == 0 && pabyData[0] == wkbNDR &&
114
0
        memcmp(pabyData + 1, "\x06\x00\x00\x00\x01\x00\x00\x00", 8) == 0)
115
0
    {
116
        // Optimization to import a Intel-ordered 1-part multipolyon on
117
        // top of an existing 1-part multipolygon, to save dynamic memory
118
        // allocations.
119
0
        const size_t nDataOffset = 9;
120
0
        size_t nBytesConsumedPolygon = 0;
121
        // cppcheck-suppress knownConditionTrueFalse
122
0
        if (nSize != static_cast<size_t>(-1))
123
0
            nSize -= nDataOffset;
124
0
        OGRErr eErr =
125
0
            cpl::down_cast<OGRPolygon *>(papoGeoms[0])
126
0
                ->OGRPolygon::importFromWkb(pabyData + nDataOffset, nSize,
127
0
                                            eWkbVariant, nBytesConsumedPolygon);
128
0
        if (eErr == OGRERR_NONE)
129
0
        {
130
0
            nBytesConsumedOut = nDataOffset + nBytesConsumedPolygon;
131
0
        }
132
0
        else
133
0
        {
134
0
            empty();
135
0
        }
136
0
        return eErr;
137
0
    }
138
139
0
    return OGRGeometryCollection::importFromWkbInternal(
140
0
        pabyData, nSize, /*nRecLevel=*/0, eWkbVariant, nBytesConsumedOut);
141
0
}
142
143
/************************************************************************/
144
/*                            exportToWkt()                             */
145
/************************************************************************/
146
147
std::string OGRMultiPolygon::exportToWkt(const OGRWktOptions &opts,
148
                                         OGRErr *err) const
149
0
{
150
0
    return exportToWktInternal(opts, err, "POLYGON");
151
0
}
152
153
/************************************************************************/
154
/*                         hasCurveGeometry()                           */
155
/************************************************************************/
156
157
OGRBoolean OGRMultiPolygon::hasCurveGeometry(int /* bLookForNonLinear */) const
158
494
{
159
494
    return FALSE;
160
494
}
161
162
/************************************************************************/
163
/*                          CastToMultiSurface()                        */
164
/************************************************************************/
165
166
/**
167
 * \brief Cast to multisurface.
168
 *
169
 * The passed in geometry is consumed and a new one returned .
170
 *
171
 * @param poMP the input geometry - ownership is passed to the method.
172
 * @return new geometry.
173
 */
174
175
OGRMultiSurface *OGRMultiPolygon::CastToMultiSurface(OGRMultiPolygon *poMP)
176
0
{
177
0
    OGRMultiSurface *poMS = new OGRMultiSurface();
178
0
    TransferMembersAndDestroy(poMP, poMS);
179
0
    return poMS;
180
0
}
181
182
/************************************************************************/
183
/*               _addGeometryWithExpectedSubGeometryType()              */
184
/*      Only to be used in conjunction with OGRPolyhedralSurface.       */
185
/*                        DO NOT USE IT ELSEWHERE.                      */
186
/************************************************************************/
187
188
//! @cond Doxygen_Suppress
189
OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType(
190
    const OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType)
191
192
0
{
193
0
    OGRGeometry *poClone = poNewGeom->clone();
194
0
    OGRErr eErr;
195
196
0
    if (poClone == nullptr)
197
0
        return OGRERR_FAILURE;
198
0
    eErr = _addGeometryDirectlyWithExpectedSubGeometryType(poClone,
199
0
                                                           eSubGeometryType);
200
0
    if (eErr != OGRERR_NONE)
201
0
        delete poClone;
202
203
0
    return eErr;
204
0
}
205
206
//! @endcond
207
208
/************************************************************************/
209
/*                 _addGeometryDirectlyWithExpectedSubGeometryType()    */
210
/*      Only to be used in conjunction with OGRPolyhedralSurface.       */
211
/*                        DO NOT USE IT ELSEWHERE.                      */
212
/************************************************************************/
213
214
//! @cond Doxygen_Suppress
215
OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType(
216
    OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType)
217
73
{
218
73
    if (wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType)
219
0
        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
220
221
73
    HomogenizeDimensionalityWith(poNewGeom);
222
223
73
    OGRGeometry **papoNewGeoms = static_cast<OGRGeometry **>(
224
73
        VSI_REALLOC_VERBOSE(papoGeoms, sizeof(void *) * (nGeomCount + 1)));
225
73
    if (papoNewGeoms == nullptr)
226
0
        return OGRERR_FAILURE;
227
228
73
    papoGeoms = papoNewGeoms;
229
73
    papoGeoms[nGeomCount] = poNewGeom;
230
73
    nGeomCount++;
231
232
73
    return OGRERR_NONE;
233
73
}
234
235
//! @endcond