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 : * 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 : 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 9 : OGRMultiPolygon &OGRMultiPolygon::operator=(const OGRMultiPolygon &other) 50 : { 51 9 : if (this != &other) 52 : { 53 8 : OGRMultiSurface::operator=(other); 54 : } 55 9 : return *this; 56 : } 57 : 58 : /************************************************************************/ 59 : /* clone() */ 60 : /************************************************************************/ 61 : 62 17079 : OGRMultiPolygon *OGRMultiPolygon::clone() const 63 : 64 : { 65 17079 : auto ret = new (std::nothrow) OGRMultiPolygon(*this); 66 17079 : if (ret) 67 : { 68 17079 : if (ret->WkbSize() != WkbSize()) 69 : { 70 0 : delete ret; 71 0 : ret = nullptr; 72 : } 73 : } 74 17079 : return ret; 75 : } 76 : 77 : /************************************************************************/ 78 : /* getGeometryType() */ 79 : /************************************************************************/ 80 : 81 49485 : OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const 82 : 83 : { 84 49485 : if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED)) 85 3256 : return wkbMultiPolygonZM; 86 46229 : else if (flags & OGR_G_MEASURED) 87 345 : return wkbMultiPolygonM; 88 45884 : else if (flags & OGR_G_3D) 89 7462 : return wkbMultiPolygon25D; 90 : else 91 38422 : return wkbMultiPolygon; 92 : } 93 : 94 : /************************************************************************/ 95 : /* getGeometryName() */ 96 : /************************************************************************/ 97 : 98 3108 : const char *OGRMultiPolygon::getGeometryName() const 99 : 100 : { 101 3108 : return "MULTIPOLYGON"; 102 : } 103 : 104 : /************************************************************************/ 105 : /* isCompatibleSubType() */ 106 : /************************************************************************/ 107 : 108 : OGRBoolean 109 126369 : OGRMultiPolygon::isCompatibleSubType(OGRwkbGeometryType eGeomType) const 110 : { 111 126369 : return wkbFlatten(eGeomType) == wkbPolygon; 112 : } 113 : 114 : /************************************************************************/ 115 : /* importFromWkb() */ 116 : /************************************************************************/ 117 : 118 2075 : OGRErr OGRMultiPolygon::importFromWkb(const unsigned char *pabyData, 119 : size_t nSize, OGRwkbVariant eWkbVariant, 120 : size_t &nBytesConsumedOut) 121 : 122 : { 123 2075 : if (nGeomCount == 1 && nSize >= 9 && flags == 0 && pabyData[0] == wkbNDR && 124 3 : memcmp(pabyData + 1, "\x06\x00\x00\x00\x01\x00\x00\x00", 8) == 0) 125 : { 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 3 : const size_t nDataOffset = 9; 130 3 : size_t nBytesConsumedPolygon = 0; 131 : // cppcheck-suppress knownConditionTrueFalse 132 3 : if (nSize != static_cast<size_t>(-1)) 133 2 : nSize -= nDataOffset; 134 : OGRErr eErr = 135 3 : cpl::down_cast<OGRPolygon *>(papoGeoms[0]) 136 3 : ->OGRPolygon::importFromWkb(pabyData + nDataOffset, nSize, 137 : eWkbVariant, nBytesConsumedPolygon); 138 3 : if (eErr == OGRERR_NONE) 139 : { 140 2 : nBytesConsumedOut = nDataOffset + nBytesConsumedPolygon; 141 : } 142 : else 143 : { 144 1 : empty(); 145 : } 146 3 : return eErr; 147 : } 148 : 149 2072 : return OGRGeometryCollection::importFromWkbInternal( 150 2072 : pabyData, nSize, /*nRecLevel=*/0, eWkbVariant, nBytesConsumedOut); 151 : } 152 : 153 : /************************************************************************/ 154 : /* exportToWkt() */ 155 : /************************************************************************/ 156 : 157 500 : std::string OGRMultiPolygon::exportToWkt(const OGRWktOptions &opts, 158 : OGRErr *err) const 159 : { 160 500 : return exportToWktInternal(opts, err, "POLYGON"); 161 : } 162 : 163 : /************************************************************************/ 164 : /* hasCurveGeometry() */ 165 : /************************************************************************/ 166 : 167 6622 : OGRBoolean OGRMultiPolygon::hasCurveGeometry(int /* bLookForNonLinear */) const 168 : { 169 6622 : return FALSE; 170 : } 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 15 : OGRMultiSurface *OGRMultiPolygon::CastToMultiSurface(OGRMultiPolygon *poMP) 186 : { 187 15 : OGRMultiSurface *poMS = new OGRMultiSurface(); 188 15 : TransferMembersAndDestroy(poMP, poMS); 189 15 : return poMS; 190 : } 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 0 : OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType( 200 : const OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType) 201 : 202 : { 203 0 : OGRGeometry *poClone = poNewGeom->clone(); 204 : OGRErr eErr; 205 : 206 0 : if (poClone == nullptr) 207 0 : return OGRERR_FAILURE; 208 0 : eErr = _addGeometryDirectlyWithExpectedSubGeometryType(poClone, 209 : eSubGeometryType); 210 0 : if (eErr != OGRERR_NONE) 211 0 : delete poClone; 212 : 213 0 : return eErr; 214 : } 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 424 : OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType( 226 : OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType) 227 : { 228 424 : if (wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType) 229 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; 230 : 231 424 : HomogenizeDimensionalityWith(poNewGeom); 232 : 233 : OGRGeometry **papoNewGeoms = static_cast<OGRGeometry **>( 234 424 : VSI_REALLOC_VERBOSE(papoGeoms, sizeof(void *) * (nGeomCount + 1))); 235 424 : if (papoNewGeoms == nullptr) 236 0 : return OGRERR_FAILURE; 237 : 238 424 : papoGeoms = papoNewGeoms; 239 424 : papoGeoms[nGeomCount] = poNewGeom; 240 424 : nGeomCount++; 241 : 242 424 : return OGRERR_NONE; 243 : } 244 : 245 : //! @endcond