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 CPL_CVSID("$Id: ogrmultipolygon.cpp 464e5bd63b59963407c8adc30fcbd5899731eddc 2021-03-16 15:06:30 +0100 Even Rouault $")
38 
39 /************************************************************************/
40 /*                          OGRMultiPolygon()                           */
41 /************************************************************************/
42 
43 /**
44  * \brief Create an empty multi polygon collection.
45  */
46 
47 OGRMultiPolygon::OGRMultiPolygon() = default;
48 
49 /************************************************************************/
50 /*              OGRMultiPolygon( const OGRMultiPolygon& )               */
51 /************************************************************************/
52 
53 /**
54  * \brief Copy constructor.
55  *
56  * Note: before GDAL 2.1, only the default implementation of the constructor
57  * existed, which could be unsafe to use.
58  *
59  * @since GDAL 2.1
60  */
61 
62 OGRMultiPolygon::OGRMultiPolygon( const OGRMultiPolygon& ) = default;
63 
64 /************************************************************************/
65 /*                         ~OGRMultiPolygon()                           */
66 /************************************************************************/
67 
68 OGRMultiPolygon::~OGRMultiPolygon() = default;
69 
70 /************************************************************************/
71 /*                  operator=( const OGRMultiPolygon&)                    */
72 /************************************************************************/
73 
74 /**
75  * \brief Assignment operator.
76  *
77  * Note: before GDAL 2.1, only the default implementation of the operator
78  * existed, which could be unsafe to use.
79  *
80  * @since GDAL 2.1
81  */
82 
operator =(const OGRMultiPolygon & other)83 OGRMultiPolygon& OGRMultiPolygon::operator=( const OGRMultiPolygon& other )
84 {
85     if( this != &other)
86     {
87         OGRMultiSurface::operator=( other );
88     }
89     return *this;
90 }
91 
92 /************************************************************************/
93 /*                               clone()                                */
94 /************************************************************************/
95 
clone() const96 OGRMultiPolygon *OGRMultiPolygon::clone() const
97 
98 {
99     return new (std::nothrow) OGRMultiPolygon(*this);
100 }
101 
102 /************************************************************************/
103 /*                          getGeometryType()                           */
104 /************************************************************************/
105 
getGeometryType() const106 OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const
107 
108 {
109     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
110         return wkbMultiPolygonZM;
111     else if( flags & OGR_G_MEASURED )
112         return wkbMultiPolygonM;
113     else if( flags & OGR_G_3D )
114         return wkbMultiPolygon25D;
115     else
116         return wkbMultiPolygon;
117 }
118 
119 /************************************************************************/
120 /*                          getGeometryName()                           */
121 /************************************************************************/
122 
getGeometryName() const123 const char * OGRMultiPolygon::getGeometryName() const
124 
125 {
126     return "MULTIPOLYGON";
127 }
128 
129 /************************************************************************/
130 /*                          isCompatibleSubType()                       */
131 /************************************************************************/
132 
133 OGRBoolean
isCompatibleSubType(OGRwkbGeometryType eGeomType) const134 OGRMultiPolygon::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
135 {
136     return wkbFlatten(eGeomType) == wkbPolygon;
137 }
138 
139 /************************************************************************/
140 /*                            exportToWkt()                             */
141 /************************************************************************/
142 
exportToWkt(const OGRWktOptions & opts,OGRErr * err) const143 std::string OGRMultiPolygon::exportToWkt(const OGRWktOptions& opts, OGRErr *err) const
144 {
145     return exportToWktInternal(opts, err, "POLYGON");
146 }
147 
148 /************************************************************************/
149 /*                         hasCurveGeometry()                           */
150 /************************************************************************/
151 
152 OGRBoolean
hasCurveGeometry(int) const153 OGRMultiPolygon::hasCurveGeometry( int /* bLookForNonLinear */ ) const
154 {
155     return FALSE;
156 }
157 
158 /************************************************************************/
159 /*                          CastToMultiSurface()                        */
160 /************************************************************************/
161 
162 /**
163  * \brief Cast to multisurface.
164  *
165  * The passed in geometry is consumed and a new one returned .
166  *
167  * @param poMP the input geometry - ownership is passed to the method.
168  * @return new geometry.
169  */
170 
CastToMultiSurface(OGRMultiPolygon * poMP)171 OGRMultiSurface* OGRMultiPolygon::CastToMultiSurface( OGRMultiPolygon* poMP )
172 {
173     OGRMultiSurface* poMS = new OGRMultiSurface();
174     TransferMembersAndDestroy(poMP, poMS);
175     return poMS;
176 }
177 
178 
179 /************************************************************************/
180 /*               _addGeometryWithExpectedSubGeometryType()              */
181 /*      Only to be used in conjunction with OGRPolyhedralSurface.       */
182 /*                        DO NOT USE IT ELSEWHERE.                      */
183 /************************************************************************/
184 
185 //! @cond Doxygen_Suppress
_addGeometryWithExpectedSubGeometryType(const OGRGeometry * poNewGeom,OGRwkbGeometryType eSubGeometryType)186 OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType(
187                                       const OGRGeometry * poNewGeom,
188                                       OGRwkbGeometryType eSubGeometryType )
189 
190 {
191     OGRGeometry *poClone = poNewGeom->clone();
192     OGRErr      eErr;
193 
194     if( poClone == nullptr )
195         return OGRERR_FAILURE;
196     eErr = _addGeometryDirectlyWithExpectedSubGeometryType( poClone, eSubGeometryType );
197     if( eErr != OGRERR_NONE )
198         delete poClone;
199 
200     return eErr;
201 }
202 //! @endcond
203 
204 /************************************************************************/
205 /*                 _addGeometryDirectlyWithExpectedSubGeometryType()    */
206 /*      Only to be used in conjunction with OGRPolyhedralSurface.       */
207 /*                        DO NOT USE IT ELSEWHERE.                      */
208 /************************************************************************/
209 
210 //! @cond Doxygen_Suppress
_addGeometryDirectlyWithExpectedSubGeometryType(OGRGeometry * poNewGeom,OGRwkbGeometryType eSubGeometryType)211 OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType(
212                                       OGRGeometry * poNewGeom,
213                                       OGRwkbGeometryType eSubGeometryType )
214 {
215     if ( wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType)
216         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
217 
218     HomogenizeDimensionalityWith(poNewGeom);
219 
220     OGRGeometry** papoNewGeoms = static_cast<OGRGeometry **>(
221         VSI_REALLOC_VERBOSE( papoGeoms, sizeof(void*) * (nGeomCount+1) ));
222     if( papoNewGeoms == nullptr )
223         return OGRERR_FAILURE;
224 
225     papoGeoms = papoNewGeoms;
226     papoGeoms[nGeomCount] = poNewGeom;
227     nGeomCount++;
228 
229     return OGRERR_NONE;
230 }
231 //! @endcond
232 
233