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 : 29 : OGRMultiPolygon::OGRMultiPolygon(const OGRMultiPolygon &) = default; 30 : 31 : /************************************************************************/ 32 : /* operator=( const OGRMultiPolygon&) */ 33 : /************************************************************************/ 34 : 35 : /** 36 : * \brief Assignment operator. 37 : */ 38 : 39 9 : OGRMultiPolygon &OGRMultiPolygon::operator=(const OGRMultiPolygon &other) 40 : { 41 9 : if (this != &other) 42 : { 43 8 : OGRMultiSurface::operator=(other); 44 : } 45 9 : return *this; 46 : } 47 : 48 : /************************************************************************/ 49 : /* clone() */ 50 : /************************************************************************/ 51 : 52 16777 : OGRMultiPolygon *OGRMultiPolygon::clone() const 53 : 54 : { 55 16777 : auto ret = new (std::nothrow) OGRMultiPolygon(*this); 56 16777 : if (ret) 57 : { 58 16777 : if (ret->WkbSize() != WkbSize()) 59 : { 60 0 : delete ret; 61 0 : ret = nullptr; 62 : } 63 : } 64 16777 : return ret; 65 : } 66 : 67 : /************************************************************************/ 68 : /* getGeometryType() */ 69 : /************************************************************************/ 70 : 71 46262 : OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const 72 : 73 : { 74 46262 : if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED)) 75 3333 : return wkbMultiPolygonZM; 76 42929 : else if (flags & OGR_G_MEASURED) 77 371 : return wkbMultiPolygonM; 78 42558 : else if (flags & OGR_G_3D) 79 6709 : return wkbMultiPolygon25D; 80 : else 81 35849 : return wkbMultiPolygon; 82 : } 83 : 84 : /************************************************************************/ 85 : /* getGeometryName() */ 86 : /************************************************************************/ 87 : 88 3084 : const char *OGRMultiPolygon::getGeometryName() const 89 : 90 : { 91 3084 : return "MULTIPOLYGON"; 92 : } 93 : 94 : /************************************************************************/ 95 : /* isCompatibleSubType() */ 96 : /************************************************************************/ 97 : 98 : OGRBoolean 99 126836 : OGRMultiPolygon::isCompatibleSubType(OGRwkbGeometryType eGeomType) const 100 : { 101 126836 : return wkbFlatten(eGeomType) == wkbPolygon; 102 : } 103 : 104 : /************************************************************************/ 105 : /* importFromWkb() */ 106 : /************************************************************************/ 107 : 108 2108 : OGRErr OGRMultiPolygon::importFromWkb(const unsigned char *pabyData, 109 : size_t nSize, OGRwkbVariant eWkbVariant, 110 : size_t &nBytesConsumedOut) 111 : 112 : { 113 2108 : if (nGeomCount == 1 && nSize >= 9 && flags == 0 && pabyData[0] == wkbNDR && 114 3 : memcmp(pabyData + 1, "\x06\x00\x00\x00\x01\x00\x00\x00", 8) == 0) 115 : { 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 3 : const size_t nDataOffset = 9; 120 3 : size_t nBytesConsumedPolygon = 0; 121 : // cppcheck-suppress knownConditionTrueFalse 122 3 : if (nSize != static_cast<size_t>(-1)) 123 2 : nSize -= nDataOffset; 124 : OGRErr eErr = 125 3 : cpl::down_cast<OGRPolygon *>(papoGeoms[0]) 126 3 : ->OGRPolygon::importFromWkb(pabyData + nDataOffset, nSize, 127 : eWkbVariant, nBytesConsumedPolygon); 128 3 : if (eErr == OGRERR_NONE) 129 : { 130 2 : nBytesConsumedOut = nDataOffset + nBytesConsumedPolygon; 131 : } 132 : else 133 : { 134 1 : empty(); 135 : } 136 3 : return eErr; 137 : } 138 : 139 2105 : return OGRGeometryCollection::importFromWkbInternal( 140 2105 : pabyData, nSize, /*nRecLevel=*/0, eWkbVariant, nBytesConsumedOut); 141 : } 142 : 143 : /************************************************************************/ 144 : /* exportToWkt() */ 145 : /************************************************************************/ 146 : 147 536 : std::string OGRMultiPolygon::exportToWkt(const OGRWktOptions &opts, 148 : OGRErr *err) const 149 : { 150 536 : return exportToWktInternal(opts, err, "POLYGON"); 151 : } 152 : 153 : /************************************************************************/ 154 : /* hasCurveGeometry() */ 155 : /************************************************************************/ 156 : 157 6778 : OGRBoolean OGRMultiPolygon::hasCurveGeometry(int /* bLookForNonLinear */) const 158 : { 159 6778 : return FALSE; 160 : } 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 15 : OGRMultiSurface *OGRMultiPolygon::CastToMultiSurface(OGRMultiPolygon *poMP) 176 : { 177 15 : OGRMultiSurface *poMS = new OGRMultiSurface(); 178 15 : TransferMembersAndDestroy(poMP, poMS); 179 15 : return poMS; 180 : } 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 0 : OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType( 190 : const OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType) 191 : 192 : { 193 0 : OGRGeometry *poClone = poNewGeom->clone(); 194 : OGRErr eErr; 195 : 196 0 : if (poClone == nullptr) 197 0 : return OGRERR_FAILURE; 198 0 : eErr = _addGeometryDirectlyWithExpectedSubGeometryType(poClone, 199 : eSubGeometryType); 200 0 : if (eErr != OGRERR_NONE) 201 0 : delete poClone; 202 : 203 0 : return eErr; 204 : } 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 287 : OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType( 216 : OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType) 217 : { 218 287 : if (wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType) 219 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; 220 : 221 287 : HomogenizeDimensionalityWith(poNewGeom); 222 : 223 : OGRGeometry **papoNewGeoms = static_cast<OGRGeometry **>( 224 287 : VSI_REALLOC_VERBOSE(papoGeoms, sizeof(void *) * (nGeomCount + 1))); 225 287 : if (papoNewGeoms == nullptr) 226 0 : return OGRERR_FAILURE; 227 : 228 287 : papoGeoms = papoNewGeoms; 229 287 : papoGeoms[nGeomCount] = poNewGeom; 230 287 : nGeomCount++; 231 : 232 287 : return OGRERR_NONE; 233 : } 234 : 235 : //! @endcond