Exemple #1
0
OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
                               unsigned char * pabyData,
                               OGRwkbVariant eWkbVariant ) const

{
/* -------------------------------------------------------------------- */
/*      Set the byte order.                                             */
/* -------------------------------------------------------------------- */
    pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);

/* -------------------------------------------------------------------- */
/*      Set the geometry feature type.                                  */
/* -------------------------------------------------------------------- */
    GUInt32 nGType = getGeometryType();
    
    if ( eWkbVariant == wkbVariantIso )
        nGType = getIsoGeometryType();
    
    if( eByteOrder == wkbNDR )
        nGType = CPL_LSBWORD32( nGType );
    else
        nGType = CPL_MSBWORD32( nGType );

    memcpy( pabyData + 1, &nGType, 4 );
    
/* -------------------------------------------------------------------- */
/*      Copy in the raw data.                                           */
/* -------------------------------------------------------------------- */

    if ( IsEmpty() && eWkbVariant == wkbVariantIso )
    {
        double dNan = std::numeric_limits<double>::quiet_NaN();
        memcpy( pabyData+5, &dNan, 8 );
        memcpy( pabyData+5+8, &dNan, 8 );
        if( getCoordinateDimension() == 3 )
            memcpy( pabyData+5+16, &dNan, 8 );
    }
    else
    {
        memcpy( pabyData+5, &x, 16 );
        if( getCoordinateDimension() == 3 )
        {
            memcpy( pabyData + 5 + 16, &z, 8 );
        }
    }
    
/* -------------------------------------------------------------------- */
/*      Swap if needed.                                                 */
/* -------------------------------------------------------------------- */
    if( OGR_SWAP( eByteOrder ) )
    {
        CPL_SWAPDOUBLE( pabyData + 5 );
        CPL_SWAPDOUBLE( pabyData + 5 + 8 );

        if( getCoordinateDimension() == 3 )
            CPL_SWAPDOUBLE( pabyData + 5 + 16 );
    }

    return OGRERR_NONE;
}
Exemple #2
0
OGRErr  OGRLineString::exportToWkb( OGRwkbByteOrder eByteOrder,
                               unsigned char * pabyData ) const

{
/* -------------------------------------------------------------------- */
/*      Set the byte order.                                             */
/* -------------------------------------------------------------------- */
    pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);

/* -------------------------------------------------------------------- */
/*      Set the geometry feature type.                                  */
/* -------------------------------------------------------------------- */
    GUInt32 nGType = getGeometryType();

    if( eByteOrder == wkbNDR )
        nGType = CPL_LSBWORD32( nGType );
    else
        nGType = CPL_MSBWORD32( nGType );

    memcpy( pabyData + 1, &nGType, 4 );

/* -------------------------------------------------------------------- */
/*      Copy in the data count.                                         */
/* -------------------------------------------------------------------- */
    memcpy( pabyData+5, &nPointCount, 4 );

/* -------------------------------------------------------------------- */
/*      Copy in the raw data.                                           */
/* -------------------------------------------------------------------- */
    int         i;

    if( getCoordinateDimension() == 3 )
    {
        for( i = 0; i < nPointCount; i++ )
        {
            memcpy( pabyData + 9 + 24*i, paoPoints+i, 16 );
            memcpy( pabyData + 9 + 16 + 24*i, padfZ+i, 8 );
        }
    }
    else
        memcpy( pabyData+9, paoPoints, 16 * nPointCount );

/* -------------------------------------------------------------------- */
/*      Swap if needed.                                                 */
/* -------------------------------------------------------------------- */
    if( OGR_SWAP( eByteOrder ) )
    {
        int     nCount;

        nCount = CPL_SWAP32( nPointCount );
        memcpy( pabyData+5, &nCount, 4 );

        for( i = getCoordinateDimension() * nPointCount - 1; i >= 0; i-- )
        {
            CPL_SWAP64PTR( pabyData + 9 + 8 * i );
        }
    }

    return OGRERR_NONE;
}
Exemple #3
0
OGRErr OGRPoint::exportToWkt( char ** ppszDstText,
                              OGRwkbVariant eWkbVariant ) const

{
    char        szTextEquiv[140];
    char        szCoordinate[80];

    if ( IsEmpty() )
    {
        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
            *ppszDstText = CPLStrdup("POINT Z EMPTY");
        else
            *ppszDstText = CPLStrdup("POINT EMPTY");
    }
    else
    {
        OGRMakeWktCoordinate(szCoordinate, x, y, z, getCoordinateDimension() );
        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
            sprintf( szTextEquiv, "POINT Z (%s)", szCoordinate );
        else
            sprintf( szTextEquiv, "POINT (%s)", szCoordinate );
        *ppszDstText = CPLStrdup( szTextEquiv );
    }
    
    return OGRERR_NONE;
}
OGRwkbGeometryType OGRMultiCurve::getGeometryType() const

{
    if( getCoordinateDimension() == 3 )
        return wkbMultiCurveZ;
    else
        return wkbMultiCurve;
}
Exemple #5
0
int OGRPoint::WkbSize() const

{
    if( getCoordinateDimension() != 3 )
        return 21;
    else
        return 29;
}
OGRwkbGeometryType OGRGeometryCollection::getGeometryType() const

{
    if( getCoordinateDimension() == 3 )
        return wkbGeometryCollection25D;
    else
        return wkbGeometryCollection;
}
Exemple #7
0
OGRwkbGeometryType OGRLineString::getGeometryType()

{
    if( getCoordinateDimension() == 3 )
        return wkbLineString25D;
    else
        return wkbLineString;
}
OGRwkbGeometryType OGRMultiLineString::getGeometryType() const

{
    if( getCoordinateDimension() == 3 )
        return wkbMultiLineString25D;
    else
        return wkbMultiLineString;
}
OGRwkbGeometryType OGRMultiPoint::getGeometryType() const

{
    if( getCoordinateDimension() == 3 )
        return wkbMultiPoint25D;
    else
        return wkbMultiPoint;
}
Exemple #10
0
OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
                                 unsigned char * pabyData ) const

{
    int         nOffset;
    int         b3D = getCoordinateDimension() == 3;
    
/* -------------------------------------------------------------------- */
/*      Set the byte order.                                             */
/* -------------------------------------------------------------------- */
    pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);

/* -------------------------------------------------------------------- */
/*      Set the geometry feature type.                                  */
/* -------------------------------------------------------------------- */
    GUInt32 nGType = getGeometryType();
    
    if( eByteOrder == wkbNDR )
        nGType = CPL_LSBWORD32( nGType );
    else
        nGType = CPL_MSBWORD32( nGType );

    memcpy( pabyData + 1, &nGType, 4 );
    
/* -------------------------------------------------------------------- */
/*      Copy in the raw data.                                           */
/* -------------------------------------------------------------------- */
    if( OGR_SWAP( eByteOrder ) )
    {
        int     nCount;

        nCount = CPL_SWAP32( nRingCount );
        memcpy( pabyData+5, &nCount, 4 );
    }
    else
    {
        memcpy( pabyData+5, &nRingCount, 4 );
    }
    
    nOffset = 9;
    
/* ==================================================================== */
/*      Serialize each of the rings.                                    */
/* ==================================================================== */
    for( int iRing = 0; iRing < nRingCount; iRing++ )
    {
        papoRings[iRing]->_exportToWkb( eByteOrder, b3D,
                                        pabyData + nOffset );

        nOffset += papoRings[iRing]->_WkbSize(b3D);
    }
    
    return OGRERR_NONE;
}
Exemple #11
0
void    OGRLineString::getPoint( int i, OGRPoint * poPoint )

{
    assert( i >= 0 );
    assert( i < nPointCount );
    assert( poPoint != NULL );

    poPoint->setX( paoPoints[i].x );
    poPoint->setY( paoPoints[i].y );

    if( getCoordinateDimension() == 3 )
        poPoint->setZ( padfZ[i] );
}
Exemple #12
0
int OGRPolygon::WkbSize() const

{
    int         nSize = 9;
    int         b3D = getCoordinateDimension() == 3;

    for( int i = 0; i < nRingCount; i++ )
    {
        nSize += papoRings[i]->_WkbSize( b3D );
    }

    return nSize;
}
Exemple #13
0
void OGRLineString::Value( double dfDistance, OGRPoint * poPoint ) const

{
    double      dfLength = 0;
    int         i;

    if( dfDistance < 0 )
    {
        StartPoint( poPoint );
        return;
    }

    for( i = 0; i < nPointCount-1; i++ )
    {
        double      dfDeltaX, dfDeltaY, dfSegLength;

        dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
        dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
        dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);

        if (dfSegLength > 0)
        {
            if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                             dfDistance) )
            {
                double      dfRatio;

                dfRatio = (dfDistance - dfLength) / dfSegLength;

                poPoint->setX( paoPoints[i].x * (1 - dfRatio)
                               + paoPoints[i+1].x * dfRatio );
                poPoint->setY( paoPoints[i].y * (1 - dfRatio)
                               + paoPoints[i+1].y * dfRatio );

                if( getCoordinateDimension() == 3 )
                    poPoint->setZ( padfZ[i] * (1 - dfRatio)
                                   + padfZ[i] * dfRatio );

                return;
            }

            dfLength += dfSegLength;
        }
    }

    EndPoint( poPoint );
}
Exemple #14
0
void OGRLineString::setPoint( int iPoint, double xIn, double yIn, double zIn )

{
    if( iPoint >= nPointCount )
        setNumPoints( iPoint+1 );

    paoPoints[iPoint].x = xIn;
    paoPoints[iPoint].y = yIn;

    if( zIn != 0.0 )
    {
        Make3D();
        padfZ[iPoint] = zIn;
    }
    else if( getCoordinateDimension() == 3 )
    {
        padfZ[iPoint] = 0.0;
    }
}
Exemple #15
0
void OGRLinearRing::closeRings()

{
    if( nPointCount < 2 )
        return;

    if( getX(0) != getX(nPointCount-1) 
        || getY(0) != getY(nPointCount-1)
        || getZ(0) != getZ(nPointCount-1) )
    {
        /* Avoid implicit change of coordinate dimensionality
         * if z=0.0 and dim=2
         */
        if( getCoordinateDimension() == 2 )
            addPoint( getX(0), getY(0) );
        else
            addPoint( getX(0), getY(0), getZ(0) );
            
    }
}
Exemple #16
0
OGRLineString* OGRCircularString::CurveToLine(
    double dfMaxAngleStepSizeDegrees, const char* const* papszOptions ) const
{
    OGRLineString* poLine = new OGRLineString();
    poLine->assignSpatialReference(getSpatialReference());

    const bool bHasZ = getCoordinateDimension() == 3;
    for( int i = 0; i < nPointCount - 2; i += 2 )
    {
        OGRLineString* poArc = OGRGeometryFactory::curveToLineString(
            paoPoints[i].x, paoPoints[i].y, padfZ ? padfZ[i] : 0.0,
            paoPoints[i+1].x, paoPoints[i+1].y, padfZ ? padfZ[i+1] : 0.0,
            paoPoints[i+2].x, paoPoints[i+2].y, padfZ ? padfZ[i+2] : 0.0,
            bHasZ,
            dfMaxAngleStepSizeDegrees,
            papszOptions);
        poLine->addSubLineString(poArc, (i == 0) ? 0 : 1);
        delete poArc;
    }
    return poLine;
}
void OGRLinearRing::reverseWindingOrder() 

{ 
    int pos = 0; 
    OGRPoint tempPoint; 

    for( int i = 0; i < nPointCount / 2; i++ ) 
    { 
        getPoint( i, &tempPoint ); 
        pos = nPointCount - i - 1;
        if( getCoordinateDimension() == 2 )
        {
            setPoint( i, getX(pos), getY(pos) );
            setPoint( pos, tempPoint.getX(), tempPoint.getY() );
        }
        else
        {
            setPoint( i, getX(pos), getY(pos), getZ(pos) );
            setPoint( pos, tempPoint.getX(), tempPoint.getY(), tempPoint.getZ() );
        }
    } 
} 
Exemple #18
0
OGRErr OGRLineString::exportToWkt( char ** ppszReturn )

{
    int         nMaxString = nPointCount * 16 * 2 + 20;
    int         nRetLen = 0;

    *ppszReturn = (char *) VSIMalloc( nMaxString );
    if( *ppszReturn == NULL )
        return OGRERR_NOT_ENOUGH_MEMORY;

    sprintf( *ppszReturn, "%s (", getGeometryName() );

    for( int i = 0; i < nPointCount; i++ )
    {
        assert( nMaxString > (int) strlen(*ppszReturn+nRetLen) + 32 + nRetLen);
        
        if( i > 0 )
            strcat( *ppszReturn + nRetLen, "," );

        if( getCoordinateDimension() == 3 )
            strcat( *ppszReturn + nRetLen,
                    OGRMakeWktCoordinate( paoPoints[i].x,
                                          paoPoints[i].y,
                                          padfZ[i] ) );
        else
            strcat( *ppszReturn + nRetLen,
                    OGRMakeWktCoordinate( paoPoints[i].x,
                                          paoPoints[i].y,
                                          0.0 ) );

        nRetLen += strlen(*ppszReturn + nRetLen);
    }

    strcat( *ppszReturn+nRetLen, ")" );

    return OGRERR_NONE;
}
Exemple #19
0
void OGRLineString::setNumPoints( int nNewPointCount )

{
    if( nNewPointCount == 0 )
    {
        OGRFree( paoPoints );
        paoPoints = NULL;
        
        OGRFree( padfZ );
        padfZ = NULL;
        
        nPointCount = 0;
        return;
    }

    if( nNewPointCount > nPointCount )
    {
        paoPoints = (OGRRawPoint *)
            OGRRealloc(paoPoints, sizeof(OGRRawPoint) * nNewPointCount);

        assert( paoPoints != NULL );
        
        memset( paoPoints + nPointCount,
                0, sizeof(OGRRawPoint) * (nNewPointCount - nPointCount) );
        
        if( getCoordinateDimension() == 3 )
        {
            padfZ = (double *)
                OGRRealloc( padfZ, sizeof(double)*nNewPointCount );
            memset( padfZ + nPointCount, 0,
                    sizeof(double) * (nNewPointCount - nPointCount) );
        }
    }

    nPointCount = nNewPointCount;
}
Exemple #20
0
OGRErr OGRLineString::exportToWkt( char ** ppszDstText ) const

{
    int         nMaxString = nPointCount * 20 * 3 + 20;
    int         nRetLen = 0;

/* -------------------------------------------------------------------- */
/*      Handle special empty case.                                      */
/* -------------------------------------------------------------------- */
    if( nPointCount == 0 )
    {
        *ppszDstText = CPLStrdup("LINESTRING(EMPTY)");
        return OGRERR_NONE;
    }

/* -------------------------------------------------------------------- */
/*      General case.                                                   */
/* -------------------------------------------------------------------- */
    *ppszDstText = (char *) VSIMalloc( nMaxString );
    if( *ppszDstText == NULL )
        return OGRERR_NOT_ENOUGH_MEMORY;

    sprintf( *ppszDstText, "%s (", getGeometryName() );

    for( int i = 0; i < nPointCount; i++ )
    {
        if( nMaxString <= (int) strlen(*ppszDstText+nRetLen) + 32 + nRetLen )
        {
            CPLDebug( "OGR",
                      "OGRLineString::exportToWkt() ... buffer overflow.\n"
                      "nMaxString=%d, strlen(*ppszDstText) = %d, i=%d\n"
                      "*ppszDstText = %s",
                      nMaxString, strlen(*ppszDstText), i, *ppszDstText );

            VSIFree( *ppszDstText );
            *ppszDstText = NULL;
            return OGRERR_NOT_ENOUGH_MEMORY;
        }

        if( i > 0 )
            strcat( *ppszDstText + nRetLen, "," );

        nRetLen += strlen(*ppszDstText + nRetLen);
        if( getCoordinateDimension() == 3 )
            OGRMakeWktCoordinate( *ppszDstText + nRetLen,
                                  paoPoints[i].x,
                                  paoPoints[i].y,
                                  padfZ[i] );
        else
            OGRMakeWktCoordinate( *ppszDstText + nRetLen,
                                  paoPoints[i].x,
                                  paoPoints[i].y,
                                  0.0 );

        nRetLen += strlen(*ppszDstText + nRetLen);
    }

    strcat( *ppszDstText+nRetLen, ")" );

    return OGRERR_NONE;
}
Exemple #21
0
int OGRLineString::WkbSize()

{
    return 5 + 4 + 8 * nPointCount * getCoordinateDimension();
}
Exemple #22
0
OGRErr  OGRLineString::exportToWkb( OGRwkbByteOrder eByteOrder,
                               unsigned char * pabyData )

{
/* -------------------------------------------------------------------- */
/*      Set the byte order.                                             */
/* -------------------------------------------------------------------- */
    pabyData[0] = (unsigned char) eByteOrder;

/* -------------------------------------------------------------------- */
/*      Set the geometry feature type.                                  */
/* -------------------------------------------------------------------- */
    if( eByteOrder == wkbNDR )
    {
        pabyData[1] = wkbLineString;

        if( getCoordinateDimension() == 3 )
            pabyData[2] = 0x80;
        else
            pabyData[2] = 0;
        
        pabyData[3] = 0;
        pabyData[4] = 0;
    }
    else
    {
        pabyData[1] = 0;
        pabyData[2] = 0;
        
        if( getCoordinateDimension() == 3 )
            pabyData[3] = 0x80;
        else
            pabyData[3] = 0;

        pabyData[4] = wkbLineString;
    }
    
/* -------------------------------------------------------------------- */
/*      Copy in the raw data.                                           */
/* -------------------------------------------------------------------- */
    memcpy( pabyData+5, &nPointCount, 4 );

/* -------------------------------------------------------------------- */
/*      Copy in the raw data.                                           */
/* -------------------------------------------------------------------- */
    int         i;
    
    if( getCoordinateDimension() == 3 )
    {
        for( i = 0; i < nPointCount; i++ )
        {
            memcpy( pabyData + 9 + 24*i, paoPoints+i, 16 );
            memcpy( pabyData + 9 + 16 + 24*i, padfZ+i, 8 );
        }
    }
    else
        memcpy( pabyData+9, paoPoints, 16 * nPointCount );

/* -------------------------------------------------------------------- */
/*      Swap if needed.                                                 */
/* -------------------------------------------------------------------- */
    if( OGR_SWAP( eByteOrder ) )
    {
        int     nCount;

        nCount = CPL_SWAP32( nPointCount );
        memcpy( pabyData+5, &nCount, 4 );

        for( i = getCoordinateDimension() * 3 - 1; i >= 0; i-- )
        {
            CPL_SWAPDOUBLE( pabyData + 9 + 8 * i );
        }
    }
    
    return OGRERR_NONE;
}
Exemple #23
0
void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const

{
    if( dfDistance < 0 )
    {
        StartPoint( poPoint );
        return;
    }

    double dfLength = 0;

    for( int i = 0; i < nPointCount - 2; i += 2 )
    {
        const double x0 = paoPoints[i].x;
        const double y0 = paoPoints[i].y;
        const double x1 = paoPoints[i+1].x;
        const double y1 = paoPoints[i+1].y;
        const double x2 = paoPoints[i+2].x;
        const double y2 = paoPoints[i+2].y;
        double R = 0.0;
        double cx = 0.0;
        double cy = 0.0;
        double alpha0 = 0.0;
        double alpha1 = 0.0;
        double alpha2 = 0.0;

        // We have strong constraints on the number of intermediate points
        // we can add.

        if( OGRGeometryFactory::GetCurveParmeters(x0, y0, x1, y1, x2, y2,
                                                  R, cx, cy,
                                                  alpha0, alpha1, alpha2) )
        {
            // It is an arc circle.
            const double dfSegLength = fabs(alpha2 - alpha0) * R;
            if( dfSegLength > 0 )
            {
                if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                                dfDistance) )
                {
                    const double dfRatio =
                        (dfDistance - dfLength) / dfSegLength;

                    const double alpha =
                        alpha0 * (1 - dfRatio) + alpha2 * dfRatio;
                    const double x = cx + R * cos(alpha);
                    const double y = cy + R * sin(alpha);

                    poPoint->setX( x );
                    poPoint->setY( y );

                    if( getCoordinateDimension() == 3 )
                        poPoint->setZ( padfZ[i] * (1 - dfRatio)
                                    + padfZ[i+2] * dfRatio );

                    return;
                }

                dfLength += dfSegLength;
            }
        }
        else
        {
            // It is a straight line.
            const double dfSegLength = dist(x0, y0, x2, y2);
            if( dfSegLength > 0 )
            {
                if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                                dfDistance) )
                {
                    const double dfRatio =
                        (dfDistance - dfLength) / dfSegLength;

                    poPoint->setX( paoPoints[i].x * (1 - dfRatio)
                                + paoPoints[i+2].x * dfRatio );
                    poPoint->setY( paoPoints[i].y * (1 - dfRatio)
                                + paoPoints[i+2].y * dfRatio );

                    if( getCoordinateDimension() == 3 )
                        poPoint->setZ( padfZ[i] * (1 - dfRatio)
                                    + padfZ[i+2] * dfRatio );

                    return;
                }

                dfLength += dfSegLength;
            }
        }
    }

    EndPoint( poPoint );
}
Exemple #24
0
OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
                                   OGRwkbVariant eWkbVariant ) const

{
    int         nMaxString = getNumGeometries() * 22 + 128;
    int         nRetLen = 0;

/* -------------------------------------------------------------------- */
/*      Return MULTIPOINT EMPTY if we get no valid points.              */
/* -------------------------------------------------------------------- */
    if( IsEmpty() )
    {
        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
            *ppszDstText = CPLStrdup("MULTIPOINT Z EMPTY");
        else
            *ppszDstText = CPLStrdup("MULTIPOINT EMPTY");
        return OGRERR_NONE;
    }

    *ppszDstText = (char *) VSIMalloc( nMaxString );
    if( *ppszDstText == NULL )
        return OGRERR_NOT_ENOUGH_MEMORY;

    if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
        sprintf( *ppszDstText, "%s Z (", getGeometryName() );
    else
        sprintf( *ppszDstText, "%s (", getGeometryName() );

    int bMustWriteComma = FALSE;
    for( int i = 0; i < getNumGeometries(); i++ )
    {
        OGRPoint        *poPoint = (OGRPoint *) getGeometryRef( i );

        if (poPoint->IsEmpty())
        {
            CPLDebug( "OGR", "OGRMultiPoint::exportToWkt() - skipping POINT EMPTY.");
            continue;
        }

        if( bMustWriteComma )
            strcat( *ppszDstText + nRetLen, "," );
        bMustWriteComma = TRUE;

        nRetLen += strlen(*ppszDstText + nRetLen);

        if( nMaxString < nRetLen + 100 )
        {
            nMaxString = nMaxString * 2;
            *ppszDstText = (char *) CPLRealloc(*ppszDstText,nMaxString);
        }

        if( eWkbVariant == wkbVariantIso )
        {
            strcat( *ppszDstText + nRetLen, "(" );
            nRetLen ++;
        }

        OGRMakeWktCoordinate( *ppszDstText + nRetLen,
                              poPoint->getX(), 
                              poPoint->getY(),
                              poPoint->getZ(),
                              poPoint->getCoordinateDimension() );

        if( eWkbVariant == wkbVariantIso )
        {
            strcat( *ppszDstText + nRetLen, ")" );
            nRetLen ++;
        }
    }

    strcat( *ppszDstText+nRetLen, ")" );

    return OGRERR_NONE;
}
OGRErr OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
                                           unsigned char * pabyData,
                                           OGRwkbVariant eWkbVariant ) const

{
    if( eWkbVariant == wkbVariantOldOgc &&
        (wkbFlatten(getGeometryType()) == wkbMultiCurve ||
         wkbFlatten(getGeometryType()) == wkbMultiSurface) )
    {
        // Does not make sense for new geometries, so patch it.
        eWkbVariant = wkbVariantIso;
    }

/* -------------------------------------------------------------------- */
/*      Set the byte order.                                             */
/* -------------------------------------------------------------------- */
    pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER(static_cast<unsigned char>(eByteOrder));

/* -------------------------------------------------------------------- */
/*      Set the geometry feature type, ensuring that 3D flag is         */
/*      preserved.                                                      */
/* -------------------------------------------------------------------- */
    GUInt32 nGType = getGeometryType();

    if( eWkbVariant == wkbVariantIso )
        nGType = getIsoGeometryType();
    else if( eWkbVariant == wkbVariantPostGIS1 )
    {
        const bool bIs3D = wkbHasZ(static_cast<OGRwkbGeometryType>(nGType));
        nGType = wkbFlatten(nGType);
        if( nGType == wkbMultiCurve )
            nGType = POSTGIS15_MULTICURVE;
        else if( nGType == wkbMultiSurface )
            nGType = POSTGIS15_MULTISURFACE;
        if( bIs3D )
            // Yes, explicitly set wkb25DBit.
            nGType = static_cast<OGRwkbGeometryType>(nGType | wkb25DBitInternalUse);
    }

    if( OGR_SWAP( eByteOrder ) )
    {
        nGType = CPL_SWAP32(nGType);
    }

    memcpy( pabyData + 1, &nGType, 4 );

/* -------------------------------------------------------------------- */
/*      Copy in the raw data.                                           */
/* -------------------------------------------------------------------- */
    if( OGR_SWAP( eByteOrder ) )
    {
        int nCount = CPL_SWAP32( nGeomCount );
        memcpy( pabyData+5, &nCount, 4 );
    }
    else
    {
        memcpy( pabyData+5, &nGeomCount, 4 );
    }

    int nOffset = 9;

/* ==================================================================== */
/*      Serialize each of the Geoms.                                    */
/* ==================================================================== */
    int iGeom = 0;
    for( auto&& poSubGeom: *this )
    {
        poSubGeom->exportToWkb( eByteOrder, pabyData + nOffset,
                                       eWkbVariant );
        // Should normally not happen if everyone else does its job,
        // but has happened sometimes. (#6332)
        if( poSubGeom->getCoordinateDimension() !=
            getCoordinateDimension() )
        {
            CPLError(CE_Warning, CPLE_AppDefined,
                     "Sub-geometry %d has coordinate dimension %d, "
                     "but container has %d",
                     iGeom,
                     poSubGeom->getCoordinateDimension(),
                     getCoordinateDimension() );
        }

        nOffset += poSubGeom->WkbSize();
        iGeom ++;
    }

    return OGRERR_NONE;
}
OGRErr OGRPolygon::exportToWkt( char ** ppszDstText ) const

{
    char        **papszRings;
    int         iRing, nCumulativeLength = 0, nNonEmptyRings = 0;
    OGRErr      eErr;
    int         bMustWriteComma = FALSE;

/* -------------------------------------------------------------------- */
/*      If we have no valid exterior ring, return POLYGON EMPTY.        */
/* -------------------------------------------------------------------- */
    if (getExteriorRing() == NULL ||
        getExteriorRing()->IsEmpty())
    {
        *ppszDstText = CPLStrdup("POLYGON EMPTY");
        return OGRERR_NONE;
    }

/* -------------------------------------------------------------------- */
/*      Build a list of strings containing the stuff for each ring.     */
/* -------------------------------------------------------------------- */
    papszRings = (char **) CPLCalloc(sizeof(char *),nRingCount);

    for( iRing = 0; iRing < nRingCount; iRing++ )
    {
        papoRings[iRing]->setCoordinateDimension( getCoordinateDimension() );
        if( papoRings[iRing]->getNumPoints() == 0 )
        {
            papszRings[iRing] = NULL;
            continue;
        }

        eErr = papoRings[iRing]->exportToWkt( &(papszRings[iRing]) );
        if( eErr != OGRERR_NONE )
            goto error;

        CPLAssert( EQUALN(papszRings[iRing],"LINEARRING (", 12) );
        nCumulativeLength += strlen(papszRings[iRing] + 11);

        nNonEmptyRings++;
    }

/* -------------------------------------------------------------------- */
/*      Allocate exactly the right amount of space for the              */
/*      aggregated string.                                              */
/* -------------------------------------------------------------------- */
    *ppszDstText = (char *) VSIMalloc(nCumulativeLength + nNonEmptyRings + 11);

    if( *ppszDstText == NULL )
    {
        eErr = OGRERR_NOT_ENOUGH_MEMORY;
        goto error;
    }

/* -------------------------------------------------------------------- */
/*      Build up the string, freeing temporary strings as we go.        */
/* -------------------------------------------------------------------- */
    strcpy( *ppszDstText, "POLYGON (" );
    nCumulativeLength = strlen(*ppszDstText);

    for( iRing = 0; iRing < nRingCount; iRing++ )
    {                                                           
        if( papszRings[iRing] == NULL )
        {
            CPLDebug( "OGR", "OGRPolygon::exportToWkt() - skipping empty ring.");
            continue;
        }

        if( bMustWriteComma )
            (*ppszDstText)[nCumulativeLength++] = ',';
        bMustWriteComma = TRUE;
        
        int nRingLen = strlen(papszRings[iRing] + 11);
        memcpy( *ppszDstText + nCumulativeLength, papszRings[iRing] + 11, nRingLen );
        nCumulativeLength += nRingLen;
        VSIFree( papszRings[iRing] );
    }

    (*ppszDstText)[nCumulativeLength++] = ')';
    (*ppszDstText)[nCumulativeLength] = '\0';

    CPLFree( papszRings );

    return OGRERR_NONE;

error:
    for( iRing = 0; iRing < nRingCount; iRing++ )
        CPLFree(papszRings[iRing]);
    CPLFree(papszRings);
    return eErr;
}