gdal/ogr/ogrtriangulatedsurface.cpp

276 lines
9.0 KiB
C++

/******************************************************************************
* $Id$
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: The OGRTriangulatedSurface geometry class.
* Author: Avyav Kumar Singh <avyavkumar at gmail dot com>
*
******************************************************************************
* Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
* Copyright (c) 2016, Even Rouault <even.roauult at spatialys.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#include "ogr_geometry.h"
#include "ogr_p.h"
#include "ogr_api.h"
/************************************************************************/
/* OGRTriangulatedSurface() */
/************************************************************************/
/**
* \brief Constructor.
*
*/
OGRTriangulatedSurface::OGRTriangulatedSurface() = default;
/************************************************************************/
/* OGRTriangulatedSurface( const OGRTriangulatedSurface& ) */
/************************************************************************/
/**
* \brief Copy constructor.
*
*/
OGRTriangulatedSurface::OGRTriangulatedSurface(
const OGRTriangulatedSurface &other)
: OGRPolyhedralSurface()
{
*this = other;
}
/************************************************************************/
/* ~OGRTriangulatedSurface() */
/************************************************************************/
/**
* \brief Destructor
*
*/
OGRTriangulatedSurface::~OGRTriangulatedSurface() = default;
/************************************************************************/
/* operator=( const OGRTriangulatedSurface&) */
/************************************************************************/
/**
* \brief Assignment operator.
*
*/
OGRTriangulatedSurface &
OGRTriangulatedSurface::operator=(const OGRTriangulatedSurface &other)
{
if (this != &other)
{
// We need to do it manually. We cannot rely on the = operator
// of OGRPolyhedralSurface since it will be confused by a multipolygon
// of triangles.
OGRSurface::operator=(other);
empty();
set3D(other.Is3D());
setMeasured(other.IsMeasured());
assignSpatialReference(other.getSpatialReference());
for (int i = 0; i < other.oMP.nGeomCount; i++)
{
OGRTriangulatedSurface::addGeometry(other.oMP.getGeometryRef(i));
}
}
return *this;
}
/************************************************************************/
/* clone() */
/************************************************************************/
OGRTriangulatedSurface *OGRTriangulatedSurface::clone() const
{
return new (std::nothrow) OGRTriangulatedSurface(*this);
}
/************************************************************************/
/* getGeometryName() */
/************************************************************************/
/**
* \brief Returns the geometry name of the TriangulatedSurface
*
* @return "TIN"
*
*/
const char *OGRTriangulatedSurface::getGeometryName() const
{
return "TIN";
}
/************************************************************************/
/* getGeometryType() */
/************************************************************************/
/**
* \brief Returns the WKB Type of TriangulatedSurface
*
*/
OGRwkbGeometryType OGRTriangulatedSurface::getGeometryType() const
{
if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
return wkbTINZM;
else if (flags & OGR_G_MEASURED)
return wkbTINM;
else if (flags & OGR_G_3D)
return wkbTINZ;
else
return wkbTIN;
}
/************************************************************************/
/* isCompatibleSubType() */
/************************************************************************/
//! @cond Doxygen_Suppress
OGRBoolean
OGRTriangulatedSurface::isCompatibleSubType(OGRwkbGeometryType eSubType) const
{
return wkbFlatten(eSubType) == wkbTriangle;
}
//! @endcond
/************************************************************************/
/* getSubGeometryName() */
/************************************************************************/
//! @cond Doxygen_Suppress
const char *OGRTriangulatedSurface::getSubGeometryName() const
{
return "TRIANGLE";
}
//! @endcond
/************************************************************************/
/* getSubGeometryType() */
/************************************************************************/
//! @cond Doxygen_Suppress
OGRwkbGeometryType OGRTriangulatedSurface::getSubGeometryType() const
{
return wkbTriangle;
}
//! @endcond
/************************************************************************/
/* addGeometry() */
/************************************************************************/
OGRErr OGRTriangulatedSurface::addGeometry(const OGRGeometry *poNewGeom)
{
// If the geometry is a polygon, check if it can be cast as a triangle
if (EQUAL(poNewGeom->getGeometryName(), "POLYGON"))
{
OGRErr eErr = OGRERR_FAILURE;
OGRTriangle *poTriangle =
new OGRTriangle(*(poNewGeom->toPolygon()), eErr);
if (poTriangle != nullptr && eErr == OGRERR_NONE)
{
eErr = addGeometryDirectly(poTriangle);
if (eErr != OGRERR_NONE)
delete poTriangle;
return eErr;
}
else
{
delete poTriangle;
return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
}
}
return OGRPolyhedralSurface::addGeometry(poNewGeom);
}
/************************************************************************/
/* GetCasterToMultiPolygon() */
/************************************************************************/
//! @cond Doxygen_Suppress
OGRPolyhedralSurfaceCastToMultiPolygon
OGRTriangulatedSurface::GetCasterToMultiPolygon() const
{
return OGRTriangulatedSurface::CastToMultiPolygonImpl;
}
/************************************************************************/
/* CastToMultiPolygon() */
/************************************************************************/
OGRMultiPolygon *
OGRTriangulatedSurface::CastToMultiPolygonImpl(OGRPolyhedralSurface *poTS)
{
OGRMultiPolygon *poMultiPolygon = new OGRMultiPolygon();
poMultiPolygon->assignSpatialReference(poTS->getSpatialReference());
for (auto &&poSubGeom : *poTS)
{
OGRPolygon *poPolygon = OGRSurface::CastToPolygon(poSubGeom);
poMultiPolygon->addGeometryDirectly(poPolygon);
poSubGeom = nullptr;
}
delete poTS;
return poMultiPolygon;
}
//! @endcond
/************************************************************************/
/* CastToPolyhedralSurface() */
/************************************************************************/
/**
* \brief Casts the OGRTriangulatedSurface to an OGRPolyhedralSurface
*
* The passed in geometry is consumed and a new one returned (or NULL in case
* of failure)
*
* @param poTS the input geometry - ownership is passed to the method.
* @return new geometry.
*/
OGRPolyhedralSurface *
OGRTriangulatedSurface::CastToPolyhedralSurface(OGRTriangulatedSurface *poTS)
{
OGRPolyhedralSurface *poPS = new OGRPolyhedralSurface();
poPS->assignSpatialReference(poTS->getSpatialReference());
for (auto &&poSubGeom : *poTS)
{
OGRPolygon *poPolygon = OGRSurface::CastToPolygon(poSubGeom);
poPS->oMP.addGeometryDirectly(poPolygon);
poSubGeom = nullptr;
}
delete poTS;
return poPS;
}