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