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 3008 : OGRMultiPolygon *OGRMultiPolygon::clone() const 53 : 54 : { 55 3008 : auto ret = new (std::nothrow) OGRMultiPolygon(*this); 56 3008 : if (ret) 57 : { 58 3008 : if (ret->WkbSize() != WkbSize()) 59 : { 60 0 : delete ret; 61 0 : ret = nullptr; 62 : } 63 : } 64 3008 : return ret; 65 : } 66 : 67 : /************************************************************************/ 68 : /* getGeometryType() */ 69 : /************************************************************************/ 70 : 71 50687 : OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const 72 : 73 : { 74 50687 : if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED)) 75 3333 : return wkbMultiPolygonZM; 76 47354 : else if (flags & OGR_G_MEASURED) 77 371 : return wkbMultiPolygonM; 78 46983 : else if (flags & OGR_G_3D) 79 7369 : return wkbMultiPolygon25D; 80 : else 81 39614 : return wkbMultiPolygon; 82 : } 83 : 84 : /************************************************************************/ 85 : /* getGeometryName() */ 86 : /************************************************************************/ 87 : 88 3518 : const char *OGRMultiPolygon::getGeometryName() const 89 : 90 : { 91 3518 : return "MULTIPOLYGON"; 92 : } 93 : 94 : /************************************************************************/ 95 : /* isCompatibleSubType() */ 96 : /************************************************************************/ 97 : 98 133299 : bool OGRMultiPolygon::isCompatibleSubType(OGRwkbGeometryType eGeomType) const 99 : { 100 133299 : return wkbFlatten(eGeomType) == wkbPolygon; 101 : } 102 : 103 : /************************************************************************/ 104 : /* importFromWkb() */ 105 : /************************************************************************/ 106 : 107 2119 : OGRErr OGRMultiPolygon::importFromWkb(const unsigned char *pabyData, 108 : size_t nSize, OGRwkbVariant eWkbVariant, 109 : size_t &nBytesConsumedOut) 110 : 111 : { 112 2119 : if (nGeomCount == 1 && nSize >= 9 && flags == 0 && pabyData[0] == wkbNDR && 113 3 : memcmp(pabyData + 1, "\x06\x00\x00\x00\x01\x00\x00\x00", 8) == 0) 114 : { 115 : // Optimization to import a Intel-ordered 1-part multipolyon on 116 : // top of an existing 1-part multipolygon, to save dynamic memory 117 : // allocations. 118 3 : const size_t nDataOffset = 9; 119 3 : size_t nBytesConsumedPolygon = 0; 120 : // cppcheck-suppress knownConditionTrueFalse 121 3 : if (nSize != static_cast<size_t>(-1)) 122 2 : nSize -= nDataOffset; 123 : OGRErr eErr = 124 3 : cpl::down_cast<OGRPolygon *>(papoGeoms[0]) 125 3 : ->OGRPolygon::importFromWkb(pabyData + nDataOffset, nSize, 126 : eWkbVariant, nBytesConsumedPolygon); 127 3 : if (eErr == OGRERR_NONE) 128 : { 129 2 : nBytesConsumedOut = nDataOffset + nBytesConsumedPolygon; 130 : } 131 : else 132 : { 133 1 : empty(); 134 : } 135 3 : return eErr; 136 : } 137 : 138 2116 : return OGRGeometryCollection::importFromWkbInternal( 139 2116 : pabyData, nSize, /*nRecLevel=*/0, eWkbVariant, nBytesConsumedOut); 140 : } 141 : 142 : /************************************************************************/ 143 : /* exportToWkt() */ 144 : /************************************************************************/ 145 : 146 533 : std::string OGRMultiPolygon::exportToWkt(const OGRWktOptions &opts, 147 : OGRErr *err) const 148 : { 149 533 : return exportToWktInternal(opts, err, "POLYGON"); 150 : } 151 : 152 : /************************************************************************/ 153 : /* hasCurveGeometry() */ 154 : /************************************************************************/ 155 : 156 7332 : bool OGRMultiPolygon::hasCurveGeometry(int /* bLookForNonLinear */) const 157 : { 158 7332 : return FALSE; 159 : } 160 : 161 : /************************************************************************/ 162 : /* CastToMultiSurface() */ 163 : /************************************************************************/ 164 : 165 : /** 166 : * \brief Cast to multisurface. 167 : * 168 : * The passed in geometry is consumed and a new one returned . 169 : * 170 : * @param poMP the input geometry - ownership is passed to the method. 171 : * @return new geometry. 172 : */ 173 : 174 15 : OGRMultiSurface *OGRMultiPolygon::CastToMultiSurface(OGRMultiPolygon *poMP) 175 : { 176 15 : OGRMultiSurface *poMS = new OGRMultiSurface(); 177 15 : TransferMembersAndDestroy(poMP, poMS); 178 15 : return poMS; 179 : } 180 : 181 : /************************************************************************/ 182 : /* _addGeometryWithExpectedSubGeometryType() */ 183 : /* Only to be used in conjunction with OGRPolyhedralSurface. */ 184 : /* DO NOT USE IT ELSEWHERE. */ 185 : /************************************************************************/ 186 : 187 : //! @cond Doxygen_Suppress 188 0 : OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType( 189 : const OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType) 190 : 191 : { 192 0 : OGRGeometry *poClone = poNewGeom->clone(); 193 : OGRErr eErr; 194 : 195 0 : if (poClone == nullptr) 196 0 : return OGRERR_FAILURE; 197 0 : eErr = _addGeometryDirectlyWithExpectedSubGeometryType(poClone, 198 : eSubGeometryType); 199 0 : if (eErr != OGRERR_NONE) 200 0 : delete poClone; 201 : 202 0 : return eErr; 203 : } 204 : 205 : //! @endcond 206 : 207 : /************************************************************************/ 208 : /* _addGeometryDirectlyWithExpectedSubGeometryType() */ 209 : /* Only to be used in conjunction with OGRPolyhedralSurface. */ 210 : /* DO NOT USE IT ELSEWHERE. */ 211 : /************************************************************************/ 212 : 213 : //! @cond Doxygen_Suppress 214 287 : OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType( 215 : OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType) 216 : { 217 287 : if (wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType) 218 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; 219 : 220 287 : HomogenizeDimensionalityWith(poNewGeom); 221 : 222 : OGRGeometry **papoNewGeoms = static_cast<OGRGeometry **>( 223 287 : VSI_REALLOC_VERBOSE(papoGeoms, sizeof(void *) * (nGeomCount + 1))); 224 287 : if (papoNewGeoms == nullptr) 225 0 : return OGRERR_FAILURE; 226 : 227 287 : papoGeoms = papoNewGeoms; 228 287 : papoGeoms[nGeomCount] = poNewGeom; 229 287 : nGeomCount++; 230 : 231 287 : return OGRERR_NONE; 232 : } 233 : 234 : //! @endcond