www.pudn.com > mitab.rar > ogrlinearring.cpp
/******************************************************************************
* $Id: ogrlinearring.cpp,v 1.18 2004/09/17 15:05:36 fwarmerdam Exp $
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: The OGRLinearRing geometry class.
* Author: Frank Warmerdam, warmerda@home.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* 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.
******************************************************************************
*
* $Log: ogrlinearring.cpp,v $
* Revision 1.18 2004/09/17 15:05:36 fwarmerdam
* added get_Area() support
*
* Revision 1.17 2004/07/10 04:51:42 warmerda
* added closeRings
*
* Revision 1.16 2004/02/21 15:36:14 warmerda
* const correctness updates for geometry: bug 289
*
* Revision 1.15 2003/09/11 22:47:54 aamici
* add class constructors and destructors where needed in order to
* let the mingw/cygwin binutils produce sensible partially linked objet files
* with 'ld -r'.
*
* Revision 1.14 2003/07/08 13:59:35 warmerda
* added poSrcRing check in copy constructor, bug 361
*
* Revision 1.13 2003/05/28 19:16:42 warmerda
* fixed up argument names and stuff for docs
*
* Revision 1.12 2003/01/14 22:13:35 warmerda
* added isClockwise() method on OGRLinearRing
*
* Revision 1.11 2002/10/24 20:38:45 warmerda
* fixed bug byte swapping point count in exporttowkb
*
* Revision 1.10 2002/05/02 19:44:53 warmerda
* fixed 3D binary support for polygon/linearring
*
* Revision 1.9 2002/04/17 21:46:22 warmerda
* Ensure padfZ copied in copy constructor.
*
* Revision 1.8 2002/02/22 22:24:31 warmerda
* fixed 3d support in clone
*
* Revision 1.7 2001/07/18 05:03:05 warmerda
* added CPL_CVSID
*
* Revision 1.6 1999/11/18 19:02:19 warmerda
* expanded tabs
*
* Revision 1.5 1999/07/08 20:25:39 warmerda
* Remove getGeometryType() method ... now returns wkbLineString.
*
* Revision 1.4 1999/06/25 20:44:43 warmerda
* implemented assignSpatialReference, carry properly
*
* Revision 1.3 1999/05/23 05:34:40 warmerda
* added support for clone(), multipolygons and geometry collections
*
* Revision 1.2 1999/05/20 14:35:44 warmerda
* added support for well known text format
*
* Revision 1.1 1999/03/30 21:21:05 warmerda
* New
*
*/
#include "ogr_geometry.h"
#include "ogr_p.h"
CPL_CVSID("$Id: ogrlinearring.cpp,v 1.18 2004/09/17 15:05:36 fwarmerdam Exp $");
/************************************************************************/
/* OGRLinearRing() */
/************************************************************************/
OGRLinearRing::OGRLinearRing()
{
}
/************************************************************************/
/* ~OGRLinearRing() */
/************************************************************************/
OGRLinearRing::~OGRLinearRing()
{
}
/************************************************************************/
/* OGRLinearRing() */
/************************************************************************/
OGRLinearRing::OGRLinearRing( OGRLinearRing * poSrcRing )
{
if( poSrcRing == NULL )
{
CPLDebug( "OGR", "OGRLinearRing::OGRLinearRing(OGRLinearRing*poSrcRing) - passed in ring is NULL!" );
return;
}
setNumPoints( poSrcRing->getNumPoints() );
memcpy( paoPoints, poSrcRing->paoPoints,
sizeof(OGRRawPoint) * getNumPoints() );
if( poSrcRing->padfZ )
{
Make3D();
memcpy( padfZ, poSrcRing->padfZ, sizeof(double) * getNumPoints() );
}
}
/************************************************************************/
/* getGeometryName() */
/************************************************************************/
const char * OGRLinearRing::getGeometryName() const
{
return "LINEARRING";
}
/************************************************************************/
/* WkbSize() */
/* */
/* Disable this method. */
/************************************************************************/
int OGRLinearRing::WkbSize() const
{
return 0;
}
/************************************************************************/
/* importFromWkb() */
/* */
/* Disable method for this class. */
/************************************************************************/
OGRErr OGRLinearRing::importFromWkb( unsigned char *pabyData, int nSize )
{
(void) pabyData;
(void) nSize;
return OGRERR_UNSUPPORTED_OPERATION;
}
/************************************************************************/
/* exportToWkb() */
/* */
/* Disable method for this class. */
/************************************************************************/
OGRErr OGRLinearRing::exportToWkb( OGRwkbByteOrder eByteOrder,
unsigned char * pabyData ) const
{
(void) eByteOrder;
(void) pabyData;
return OGRERR_UNSUPPORTED_OPERATION;
}
/************************************************************************/
/* _importFromWkb() */
/* */
/* Helper method for OGRPolygon. NOT A NORMAL importFromWkb() */
/* method! */
/************************************************************************/
OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D,
unsigned char * pabyData,
int nBytesAvailable )
{
if( nBytesAvailable < 4 && nBytesAvailable != -1 )
return OGRERR_NOT_ENOUGH_DATA;
/* -------------------------------------------------------------------- */
/* Get the vertex count. */
/* -------------------------------------------------------------------- */
int nNewNumPoints;
memcpy( &nNewNumPoints, pabyData, 4 );
if( OGR_SWAP( eByteOrder ) )
nNewNumPoints = CPL_SWAP32(nNewNumPoints);
setNumPoints( nNewNumPoints );
if( b3D )
Make3D();
else
Make2D();
/* -------------------------------------------------------------------- */
/* Get the vertices */
/* -------------------------------------------------------------------- */
int i;
if( !b3D )
memcpy( paoPoints, pabyData + 4, 16 * nPointCount );
else
{
for( int i = 0; i < nPointCount; i++ )
{
memcpy( &(paoPoints[i].x), pabyData + 4 + 24 * i, 8 );
memcpy( &(paoPoints[i].y), pabyData + 4 + 24 * i + 8, 8 );
memcpy( padfZ + i, pabyData + 4 + 24 * i + 16, 8 );
}
}
/* -------------------------------------------------------------------- */
/* Byte swap if needed. */
/* -------------------------------------------------------------------- */
if( OGR_SWAP( eByteOrder ) )
{
for( i = 0; i < nPointCount; i++ )
{
CPL_SWAPDOUBLE( &(paoPoints[i].x) );
CPL_SWAPDOUBLE( &(paoPoints[i].y) );
if( b3D )
{
CPL_SWAPDOUBLE( padfZ + i );
}
}
}
return OGRERR_NONE;
}
/************************************************************************/
/* _exportToWkb() */
/* */
/* Helper method for OGRPolygon. THIS IS NOT THE NORMAL */
/* exportToWkb() METHOD! */
/************************************************************************/
OGRErr OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int b3D,
unsigned char * pabyData ) const
{
int i, nWords;
/* -------------------------------------------------------------------- */
/* Copy in the raw data. */
/* -------------------------------------------------------------------- */
memcpy( pabyData, &nPointCount, 4 );
/* -------------------------------------------------------------------- */
/* Copy in the raw data. */
/* -------------------------------------------------------------------- */
if( b3D )
{
nWords = 3 * nPointCount;
for( i = 0; i < nPointCount; i++ )
{
memcpy( pabyData+4+i*24, &(paoPoints[i].x), 8 );
memcpy( pabyData+4+i*24+8, &(paoPoints[i].y), 8 );
if( padfZ == NULL )
memset( pabyData+4+i*24+16, 0, 8 );
else
memcpy( pabyData+4+i*24+16, padfZ + i, 8 );
}
}
else
{
nWords = 2 * nPointCount;
memcpy( pabyData+4, paoPoints, 16 * nPointCount );
}
/* -------------------------------------------------------------------- */
/* Swap if needed. */
/* -------------------------------------------------------------------- */
if( OGR_SWAP( eByteOrder ) )
{
int nCount;
nCount = CPL_SWAP32( nPointCount );
memcpy( pabyData, &nCount, 4 );
for( i = 0; i < nWords; i++ )
{
CPL_SWAPDOUBLE( pabyData + 4 + 8 * i );
}
}
return OGRERR_NONE;
}
/************************************************************************/
/* _WkbSize() */
/* */
/* Helper method for OGRPolygon. NOT THE NORMAL WkbSize() METHOD! */
/************************************************************************/
int OGRLinearRing::_WkbSize( int b3D ) const
{
if( b3D )
return 4 + 24 * nPointCount;
else
return 4 + 16 * nPointCount;
}
/************************************************************************/
/* clone() */
/* */
/* We override the OGRCurve clone() to ensure that we get the */
/* correct virtual table. */
/************************************************************************/
OGRGeometry *OGRLinearRing::clone() const
{
OGRLinearRing *poNewLinearRing;
poNewLinearRing = new OGRLinearRing();
poNewLinearRing->assignSpatialReference( getSpatialReference() );
poNewLinearRing->setPoints( nPointCount, paoPoints, padfZ );
return poNewLinearRing;
}
/************************************************************************/
/* isClockwise() */
/************************************************************************/
/**
* Returns TRUE if the ring has clockwise winding.
*
* @return TRUE if clockwise otherwise FALSE.
*/
int OGRLinearRing::isClockwise() const
{
double dfSum = 0.0;
for( int iVert = 0; iVert < nPointCount-1; iVert++ )
{
dfSum += paoPoints[iVert].x * paoPoints[iVert+1].y
- paoPoints[iVert].y * paoPoints[iVert+1].x;
}
dfSum += paoPoints[nPointCount-1].x * paoPoints[0].y
- paoPoints[nPointCount-1].y * paoPoints[0].x;
return dfSum < 0.0;
}
/************************************************************************/
/* closeRing() */
/************************************************************************/
void OGRLinearRing::closeRings()
{
if( nPointCount < 2 )
return;
if( getX(0) != getX(nPointCount-1)
|| getY(0) != getY(nPointCount-1)
|| getZ(0) != getZ(nPointCount-1) )
{
addPoint( getX(0), getY(0), getZ(0) );
}
}
/************************************************************************/
/* get_Area() */
/************************************************************************/
/**
* Compute area of ring.
*
* The area is computed according to Green's Theorem:
*
* Area is "Sum(x(i)*y(i+1) - x(i+1)*y(i))/2" for i = 0 to pointCount-1,
* assuming the last point is a duplicate of the first.
*
* @return computed area.
*/
double OGRLinearRing::get_Area() const
{
double dfAreaSum = 0.0;
int i;
for( i = 0; i < nPointCount-1; i++ )
{
dfAreaSum += 0.5 * ( paoPoints[i].x * paoPoints[i+1].y
- paoPoints[i+1].x * paoPoints[i].y );
}
dfAreaSum += 0.5 * ( paoPoints[nPointCount-1].x * paoPoints[0].y
- paoPoints[0].x * paoPoints[nPointCount-1].y );
return fabs(dfAreaSum);
}