1 /******************************************************************************
2  * $Id: ogrtriangulatedsurface.cpp 464e5bd63b59963407c8adc30fcbd5899731eddc 2021-03-16 15:06:30 +0100 Even Rouault $
3  *
4  * Project:  OpenGIS Simple Features Reference Implementation
5  * Purpose:  The OGRTriangulatedSurface geometry class.
6  * Author:   Avyav Kumar Singh <avyavkumar at gmail dot com>
7  *
8  ******************************************************************************
9  * Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
10  * Copyright (c) 2016, Even Rouault <even.roauult at spatialys.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ****************************************************************************/
30 
31 #include "ogr_geometry.h"
32 #include "ogr_p.h"
33 #include "ogr_api.h"
34 
35 CPL_CVSID("$Id: ogrtriangulatedsurface.cpp 464e5bd63b59963407c8adc30fcbd5899731eddc 2021-03-16 15:06:30 +0100 Even Rouault $")
36 
37 /************************************************************************/
38 /*                        OGRTriangulatedSurface()                      */
39 /************************************************************************/
40 
41 /**
42  * \brief Constructor.
43  *
44  */
45 
46 OGRTriangulatedSurface::OGRTriangulatedSurface() = default;
47 
48 /************************************************************************/
49 /*        OGRTriangulatedSurface( const OGRTriangulatedSurface& )       */
50 /************************************************************************/
51 
52 /**
53  * \brief Copy constructor.
54  *
55  */
56 
OGRTriangulatedSurface(const OGRTriangulatedSurface & other)57 OGRTriangulatedSurface::OGRTriangulatedSurface(
58                                         const OGRTriangulatedSurface& other ) :
59     OGRPolyhedralSurface()
60 {
61     *this = other;
62 }
63 
64 /************************************************************************/
65 /*                        ~OGRTriangulatedSurface()                     */
66 /************************************************************************/
67 
68 /**
69  * \brief Destructor
70  *
71  */
72 
73 OGRTriangulatedSurface::~OGRTriangulatedSurface() = default;
74 
75 /************************************************************************/
76 /*                 operator=( const OGRTriangulatedSurface&)            */
77 /************************************************************************/
78 
79 /**
80  * \brief Assignment operator.
81  *
82  */
83 
operator =(const OGRTriangulatedSurface & other)84 OGRTriangulatedSurface& OGRTriangulatedSurface::operator=(
85                                         const OGRTriangulatedSurface& other )
86 {
87     if( this != &other)
88     {
89         // We need to do it manually. We cannot rely on the = operator
90         // of OGRPolyhedralSurface since it will be confused by a multipolygon
91         // of triangles.
92         OGRSurface::operator=( other );
93         empty();
94         set3D( other.Is3D() );
95         setMeasured( other.IsMeasured() );
96         assignSpatialReference( other.getSpatialReference() );
97         for(int i=0;i<other.oMP.nGeomCount;i++)
98         {
99             OGRTriangulatedSurface::addGeometry( other.oMP.getGeometryRef(i) );
100         }
101     }
102     return *this;
103 }
104 
105 /************************************************************************/
106 /*                               clone()                                */
107 /************************************************************************/
108 
clone() const109 OGRTriangulatedSurface *OGRTriangulatedSurface::clone() const
110 
111 {
112     return new (std::nothrow) OGRTriangulatedSurface(*this);
113 }
114 
115 /************************************************************************/
116 /*                          getGeometryName()                           */
117 /************************************************************************/
118 
119 /**
120  * \brief Returns the geometry name of the TriangulatedSurface
121  *
122  * @return "TIN"
123  *
124  */
125 
getGeometryName() const126 const char* OGRTriangulatedSurface::getGeometryName() const
127 {
128     return "TIN" ;
129 }
130 
131 /************************************************************************/
132 /*                          getGeometryType()                           */
133 /************************************************************************/
134 
135 /**
136  * \brief Returns the WKB Type of TriangulatedSurface
137  *
138  */
139 
getGeometryType() const140 OGRwkbGeometryType OGRTriangulatedSurface::getGeometryType() const
141 {
142     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
143         return wkbTINZM;
144     else if( flags & OGR_G_MEASURED  )
145         return wkbTINM;
146     else if( flags & OGR_G_3D )
147         return wkbTINZ;
148     else
149         return wkbTIN;
150 }
151 
152 /************************************************************************/
153 /*                         isCompatibleSubType()                        */
154 /************************************************************************/
155 
156 //! @cond Doxygen_Suppress
isCompatibleSubType(OGRwkbGeometryType eSubType) const157 OGRBoolean OGRTriangulatedSurface::isCompatibleSubType(
158                                         OGRwkbGeometryType eSubType ) const
159 {
160     return wkbFlatten( eSubType ) == wkbTriangle;
161 }
162 //! @endcond
163 
164 /************************************************************************/
165 /*                         getSubGeometryName()                         */
166 /************************************************************************/
167 
168 //! @cond Doxygen_Suppress
getSubGeometryName() const169 const char* OGRTriangulatedSurface::getSubGeometryName() const
170 {
171     return "TRIANGLE";
172 }
173 //! @endcond
174 
175 /************************************************************************/
176 /*                         getSubGeometryType()                         */
177 /************************************************************************/
178 
179 //! @cond Doxygen_Suppress
getSubGeometryType() const180 OGRwkbGeometryType OGRTriangulatedSurface::getSubGeometryType() const
181 {
182     return wkbTriangle;
183 }
184 //! @endcond
185 
186 /************************************************************************/
187 /*                            addGeometry()                             */
188 /************************************************************************/
189 
addGeometry(const OGRGeometry * poNewGeom)190 OGRErr OGRTriangulatedSurface::addGeometry (const OGRGeometry *poNewGeom)
191 {
192     // If the geometry is a polygon, check if it can be cast as a triangle
193     if( EQUAL(poNewGeom->getGeometryName(),"POLYGON") )
194     {
195         OGRErr eErr = OGRERR_FAILURE;
196         OGRTriangle *poTriangle = new OGRTriangle(
197                     *(poNewGeom->toPolygon()), eErr);
198         if (poTriangle != nullptr && eErr == OGRERR_NONE)
199         {
200             eErr = addGeometryDirectly(poTriangle);
201 
202             if( eErr != OGRERR_NONE )
203                 delete poTriangle;
204 
205             return eErr;
206         }
207         else
208         {
209             delete poTriangle;
210             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
211         }
212     }
213 
214     return OGRPolyhedralSurface::addGeometry(poNewGeom);
215 }
216 
217 /************************************************************************/
218 /*                     GetCasterToMultiPolygon()                        */
219 /************************************************************************/
220 
221 //! @cond Doxygen_Suppress
222 OGRPolyhedralSurfaceCastToMultiPolygon
GetCasterToMultiPolygon() const223                         OGRTriangulatedSurface::GetCasterToMultiPolygon() const
224 {
225     return OGRTriangulatedSurface::CastToMultiPolygonImpl;
226 }
227 
228 /************************************************************************/
229 /*                         CastToMultiPolygon()                         */
230 /************************************************************************/
231 
CastToMultiPolygonImpl(OGRPolyhedralSurface * poTS)232 OGRMultiPolygon* OGRTriangulatedSurface::CastToMultiPolygonImpl(
233                                                     OGRPolyhedralSurface* poTS)
234 {
235     OGRMultiPolygon *poMultiPolygon = new OGRMultiPolygon();
236     poMultiPolygon->assignSpatialReference(poTS->getSpatialReference());
237 
238     for( auto&& poSubGeom: *poTS )
239     {
240         OGRPolygon *poPolygon = OGRSurface::CastToPolygon(poSubGeom);
241         poMultiPolygon->addGeometryDirectly(poPolygon);
242         poSubGeom = nullptr;
243     }
244     delete poTS;
245 
246     return poMultiPolygon;
247 }
248 //! @endcond
249 
250 /************************************************************************/
251 /*                     CastToPolyhedralSurface()                        */
252 /************************************************************************/
253 
254 /**
255  * \brief Casts the OGRTriangulatedSurface to an OGRPolyhedralSurface
256  *
257  * The passed in geometry is consumed and a new one returned (or NULL in case
258  * of failure)
259  *
260  * @param poTS the input geometry - ownership is passed to the method.
261  * @return new geometry.
262  */
263 
264 
CastToPolyhedralSurface(OGRTriangulatedSurface * poTS)265 OGRPolyhedralSurface* OGRTriangulatedSurface::CastToPolyhedralSurface(
266                                                 OGRTriangulatedSurface* poTS)
267 {
268     OGRPolyhedralSurface* poPS = new OGRPolyhedralSurface();
269     poPS->assignSpatialReference(poTS->getSpatialReference());
270     for( auto&& poSubGeom: *poTS )
271     {
272         OGRPolygon *poPolygon = OGRSurface::CastToPolygon(poSubGeom);
273         poPS->oMP.addGeometryDirectly(poPolygon);
274         poSubGeom = nullptr;
275     }
276     delete poTS;
277     return poPS;
278 }
279