/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 |