Line data Source code
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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_port.h"
31 : #include "ogr_geometry.h"
32 :
33 : #include "ogr_api.h"
34 : #include "ogr_core.h"
35 : #include "ogr_p.h"
36 :
37 : /************************************************************************/
38 : /* OGRMultiPolygon() */
39 : /************************************************************************/
40 :
41 : /**
42 : * \brief Create an empty multi polygon collection.
43 : */
44 :
45 : OGRMultiPolygon::OGRMultiPolygon() = default;
46 :
47 : /************************************************************************/
48 : /* OGRMultiPolygon( const OGRMultiPolygon& ) */
49 : /************************************************************************/
50 :
51 : /**
52 : * \brief Copy constructor.
53 : *
54 : * Note: before GDAL 2.1, only the default implementation of the constructor
55 : * existed, which could be unsafe to use.
56 : *
57 : * @since GDAL 2.1
58 : */
59 :
60 : OGRMultiPolygon::OGRMultiPolygon(const OGRMultiPolygon &) = default;
61 :
62 : /************************************************************************/
63 : /* ~OGRMultiPolygon() */
64 : /************************************************************************/
65 :
66 : OGRMultiPolygon::~OGRMultiPolygon() = default;
67 :
68 : /************************************************************************/
69 : /* operator=( const OGRMultiPolygon&) */
70 : /************************************************************************/
71 :
72 : /**
73 : * \brief Assignment operator.
74 : *
75 : * Note: before GDAL 2.1, only the default implementation of the operator
76 : * existed, which could be unsafe to use.
77 : *
78 : * @since GDAL 2.1
79 : */
80 :
81 9 : OGRMultiPolygon &OGRMultiPolygon::operator=(const OGRMultiPolygon &other)
82 : {
83 9 : if (this != &other)
84 : {
85 8 : OGRMultiSurface::operator=(other);
86 : }
87 9 : return *this;
88 : }
89 :
90 : /************************************************************************/
91 : /* clone() */
92 : /************************************************************************/
93 :
94 2988 : OGRMultiPolygon *OGRMultiPolygon::clone() const
95 :
96 : {
97 2988 : return new (std::nothrow) OGRMultiPolygon(*this);
98 : }
99 :
100 : /************************************************************************/
101 : /* getGeometryType() */
102 : /************************************************************************/
103 :
104 30419 : OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const
105 :
106 : {
107 30419 : if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
108 3256 : return wkbMultiPolygonZM;
109 27163 : else if (flags & OGR_G_MEASURED)
110 345 : return wkbMultiPolygonM;
111 26818 : else if (flags & OGR_G_3D)
112 4985 : return wkbMultiPolygon25D;
113 : else
114 21833 : return wkbMultiPolygon;
115 : }
116 :
117 : /************************************************************************/
118 : /* getGeometryName() */
119 : /************************************************************************/
120 :
121 2681 : const char *OGRMultiPolygon::getGeometryName() const
122 :
123 : {
124 2681 : return "MULTIPOLYGON";
125 : }
126 :
127 : /************************************************************************/
128 : /* isCompatibleSubType() */
129 : /************************************************************************/
130 :
131 : OGRBoolean
132 15862 : OGRMultiPolygon::isCompatibleSubType(OGRwkbGeometryType eGeomType) const
133 : {
134 15862 : return wkbFlatten(eGeomType) == wkbPolygon;
135 : }
136 :
137 : /************************************************************************/
138 : /* importFromWkb() */
139 : /************************************************************************/
140 :
141 2059 : OGRErr OGRMultiPolygon::importFromWkb(const unsigned char *pabyData,
142 : size_t nSize, OGRwkbVariant eWkbVariant,
143 : size_t &nBytesConsumedOut)
144 :
145 : {
146 2059 : if (nGeomCount == 1 && nSize >= 9 && flags == 0 && pabyData[0] == wkbNDR &&
147 3 : memcmp(pabyData + 1, "\x06\x00\x00\x00\x01\x00\x00\x00", 8) == 0)
148 : {
149 : // Optimization to import a Intel-ordered 1-part multipolyon on
150 : // top of an existing 1-part multipolygon, to save dynamic memory
151 : // allocations.
152 3 : const size_t nDataOffset = 9;
153 3 : size_t nBytesConsumedPolygon = 0;
154 : // cppcheck-suppress knownConditionTrueFalse
155 3 : if (nSize != static_cast<size_t>(-1))
156 2 : nSize -= nDataOffset;
157 : OGRErr eErr =
158 3 : cpl::down_cast<OGRPolygon *>(papoGeoms[0])
159 3 : ->OGRPolygon::importFromWkb(pabyData + nDataOffset, nSize,
160 : eWkbVariant, nBytesConsumedPolygon);
161 3 : if (eErr == OGRERR_NONE)
162 : {
163 2 : nBytesConsumedOut = nDataOffset + nBytesConsumedPolygon;
164 : }
165 : else
166 : {
167 1 : empty();
168 : }
169 3 : return eErr;
170 : }
171 :
172 2056 : return OGRGeometryCollection::importFromWkbInternal(
173 2056 : pabyData, nSize, /*nRecLevel=*/0, eWkbVariant, nBytesConsumedOut);
174 : }
175 :
176 : /************************************************************************/
177 : /* exportToWkt() */
178 : /************************************************************************/
179 :
180 469 : std::string OGRMultiPolygon::exportToWkt(const OGRWktOptions &opts,
181 : OGRErr *err) const
182 : {
183 469 : return exportToWktInternal(opts, err, "POLYGON");
184 : }
185 :
186 : /************************************************************************/
187 : /* hasCurveGeometry() */
188 : /************************************************************************/
189 :
190 6115 : OGRBoolean OGRMultiPolygon::hasCurveGeometry(int /* bLookForNonLinear */) const
191 : {
192 6115 : return FALSE;
193 : }
194 :
195 : /************************************************************************/
196 : /* CastToMultiSurface() */
197 : /************************************************************************/
198 :
199 : /**
200 : * \brief Cast to multisurface.
201 : *
202 : * The passed in geometry is consumed and a new one returned .
203 : *
204 : * @param poMP the input geometry - ownership is passed to the method.
205 : * @return new geometry.
206 : */
207 :
208 11 : OGRMultiSurface *OGRMultiPolygon::CastToMultiSurface(OGRMultiPolygon *poMP)
209 : {
210 11 : OGRMultiSurface *poMS = new OGRMultiSurface();
211 11 : TransferMembersAndDestroy(poMP, poMS);
212 11 : return poMS;
213 : }
214 :
215 : /************************************************************************/
216 : /* _addGeometryWithExpectedSubGeometryType() */
217 : /* Only to be used in conjunction with OGRPolyhedralSurface. */
218 : /* DO NOT USE IT ELSEWHERE. */
219 : /************************************************************************/
220 :
221 : //! @cond Doxygen_Suppress
222 0 : OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType(
223 : const OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType)
224 :
225 : {
226 0 : OGRGeometry *poClone = poNewGeom->clone();
227 : OGRErr eErr;
228 :
229 0 : if (poClone == nullptr)
230 0 : return OGRERR_FAILURE;
231 0 : eErr = _addGeometryDirectlyWithExpectedSubGeometryType(poClone,
232 : eSubGeometryType);
233 0 : if (eErr != OGRERR_NONE)
234 0 : delete poClone;
235 :
236 0 : return eErr;
237 : }
238 :
239 : //! @endcond
240 :
241 : /************************************************************************/
242 : /* _addGeometryDirectlyWithExpectedSubGeometryType() */
243 : /* Only to be used in conjunction with OGRPolyhedralSurface. */
244 : /* DO NOT USE IT ELSEWHERE. */
245 : /************************************************************************/
246 :
247 : //! @cond Doxygen_Suppress
248 418 : OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType(
249 : OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType)
250 : {
251 418 : if (wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType)
252 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
253 :
254 418 : HomogenizeDimensionalityWith(poNewGeom);
255 :
256 : OGRGeometry **papoNewGeoms = static_cast<OGRGeometry **>(
257 418 : VSI_REALLOC_VERBOSE(papoGeoms, sizeof(void *) * (nGeomCount + 1)));
258 418 : if (papoNewGeoms == nullptr)
259 0 : return OGRERR_FAILURE;
260 :
261 418 : papoGeoms = papoNewGeoms;
262 418 : papoGeoms[nGeomCount] = poNewGeom;
263 418 : nGeomCount++;
264 :
265 418 : return OGRERR_NONE;
266 : }
267 :
268 : //! @endcond
|