OGRErr OGRGeometryCollection::addGeometryDirectly( OGRGeometry * poNewGeom ) { if( !isCompatibleSubType(poNewGeom->getGeometryType()) ) return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; if( poNewGeom->Is3D() && !Is3D() ) set3D(TRUE); if( poNewGeom->IsMeasured() && !IsMeasured() ) setMeasured(TRUE); if( !poNewGeom->Is3D() && Is3D() ) poNewGeom->set3D(TRUE); if( !poNewGeom->IsMeasured() && IsMeasured() ) poNewGeom->setMeasured(TRUE); OGRGeometry** papoNewGeoms = (OGRGeometry **) VSI_REALLOC_VERBOSE( papoGeoms, sizeof(void*) * (nGeomCount+1) ); if( papoNewGeoms == NULL ) return OGRERR_FAILURE; papoGeoms = papoNewGeoms; papoGeoms[nGeomCount] = poNewGeom; nGeomCount++; return OGRERR_NONE; }
OGRErr OGRPoint::exportToWkt( char ** ppszDstText, OGRwkbVariant eWkbVariant ) const { if( IsEmpty() ) { if( eWkbVariant == wkbVariantIso ) { if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) ) *ppszDstText = CPLStrdup("POINT ZM EMPTY"); else if( flags & OGR_G_MEASURED ) *ppszDstText = CPLStrdup("POINT M EMPTY"); else if( flags & OGR_G_3D ) *ppszDstText = CPLStrdup("POINT Z EMPTY"); else *ppszDstText = CPLStrdup("POINT EMPTY"); } else { *ppszDstText = CPLStrdup("POINT EMPTY"); } } else { char szTextEquiv[180] = {}; if( eWkbVariant == wkbVariantIso ) { char szCoordinate[80] = {}; OGRMakeWktCoordinateM(szCoordinate, x, y, z, m, Is3D(), IsMeasured()); if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) ) snprintf(szTextEquiv, sizeof(szTextEquiv), "POINT ZM (%s)", szCoordinate); else if( flags & OGR_G_MEASURED ) snprintf(szTextEquiv, sizeof(szTextEquiv), "POINT M (%s)", szCoordinate); else if( flags & OGR_G_3D ) snprintf(szTextEquiv, sizeof(szTextEquiv), "POINT Z (%s)", szCoordinate); else snprintf(szTextEquiv, sizeof(szTextEquiv), "POINT (%s)", szCoordinate); } else { char szCoordinate[80] = {}; OGRMakeWktCoordinateM(szCoordinate, x, y, z, m, Is3D(), FALSE); snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT (%s)", szCoordinate ); } *ppszDstText = CPLStrdup( szTextEquiv ); } return OGRERR_NONE; }
OGRErr OGRPolygon::exportToWkt( char ** ppszDstText, OGRwkbVariant eWkbVariant ) const { bool bMustWriteComma = false; /* -------------------------------------------------------------------- */ /* If we have no valid exterior ring, return POLYGON EMPTY. */ /* -------------------------------------------------------------------- */ if( getExteriorRing() == NULL || getExteriorRing()->IsEmpty() ) { if( eWkbVariant == wkbVariantIso ) { if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) ) *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " ZM EMPTY").c_str()); else if( flags & OGR_G_MEASURED ) *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " M EMPTY").c_str()); else if( flags & OGR_G_3D ) *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " Z EMPTY").c_str()); else *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " EMPTY").c_str()); } else *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " EMPTY").c_str()); return OGRERR_NONE; } /* -------------------------------------------------------------------- */ /* Build a list of strings containing the stuff for each ring. */ /* -------------------------------------------------------------------- */ char **papszRings = static_cast<char **>(CPLCalloc(sizeof(char *), oCC.nCurveCount)); size_t nCumulativeLength = 0; size_t nNonEmptyRings = 0; size_t *pnRingBeginning = static_cast<size_t *>(CPLCalloc(sizeof(size_t), oCC.nCurveCount)); OGRErr eErr; for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ ) { OGRLinearRing* poLR = (OGRLinearRing*) oCC.papoCurves[iRing]; //poLR->setFlags( getFlags() ); poLR->set3D(Is3D()); poLR->setMeasured(IsMeasured()); if( poLR->getNumPoints() == 0 ) { papszRings[iRing] = NULL; continue; } eErr = poLR->exportToWkt( &(papszRings[iRing]), eWkbVariant ); if( eErr != OGRERR_NONE ) goto error; if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING ZM (") ) pnRingBeginning[iRing] = 14; else if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING M (") ) pnRingBeginning[iRing] = 13; else if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING Z (") ) pnRingBeginning[iRing] = 13; else if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING (") ) pnRingBeginning[iRing] = 11; else { CPLAssert(false); } nCumulativeLength += strlen(papszRings[iRing] + pnRingBeginning[iRing]); nNonEmptyRings++; } /* -------------------------------------------------------------------- */ /* Allocate exactly the right amount of space for the */ /* aggregated string. */ /* -------------------------------------------------------------------- */ *ppszDstText = (char *) VSI_MALLOC_VERBOSE( nCumulativeLength + nNonEmptyRings + strlen(getGeometryName()) + strlen(" ZM ()") + 1); if( *ppszDstText == NULL ) { eErr = OGRERR_NOT_ENOUGH_MEMORY; goto error; } /* -------------------------------------------------------------------- */ /* Build up the string, freeing temporary strings as we go. */ /* -------------------------------------------------------------------- */ if( eWkbVariant == wkbVariantIso ) { if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) ) strcpy( *ppszDstText, (CPLString(getGeometryName()) + " ZM (").c_str() ); else if( flags & OGR_G_MEASURED ) strcpy( *ppszDstText, (CPLString(getGeometryName()) + " M (").c_str() ); else if( flags & OGR_G_3D ) strcpy( *ppszDstText, (CPLString(getGeometryName()) + " Z (").c_str() ); else strcpy( *ppszDstText, (CPLString(getGeometryName()) + " (").c_str() ); } else strcpy( *ppszDstText, (CPLString(getGeometryName()) + " (").c_str() ); nCumulativeLength = strlen(*ppszDstText); for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ ) { if( papszRings[iRing] == NULL ) { CPLDebug( "OGR", "OGRPolygon::exportToWkt() - skipping empty ring."); continue; } if( bMustWriteComma ) (*ppszDstText)[nCumulativeLength++] = ','; bMustWriteComma = true; size_t nRingLen = strlen(papszRings[iRing] + pnRingBeginning[iRing]); memcpy( *ppszDstText + nCumulativeLength, papszRings[iRing] + pnRingBeginning[iRing], nRingLen ); nCumulativeLength += nRingLen; VSIFree( papszRings[iRing] ); } (*ppszDstText)[nCumulativeLength++] = ')'; (*ppszDstText)[nCumulativeLength] = '\0'; CPLFree( papszRings ); CPLFree( pnRingBeginning ); return OGRERR_NONE; error: for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ ) CPLFree(papszRings[iRing]); CPLFree(papszRings); return eErr; }
OGRErr OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder, unsigned char * pabyData, OGRwkbVariant eWkbVariant ) const { /* -------------------------------------------------------------------- */ /* Set the byte order. */ /* -------------------------------------------------------------------- */ pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER(static_cast<unsigned char>(eByteOrder)); /* -------------------------------------------------------------------- */ /* Set the geometry feature type. */ /* -------------------------------------------------------------------- */ GUInt32 nGType = getGeometryType(); if( eWkbVariant == wkbVariantPostGIS1 ) { nGType = wkbFlatten(nGType); if( Is3D() ) // Explicitly set wkb25DBit. nGType = static_cast<OGRwkbGeometryType>(nGType | wkb25DBitInternalUse); if( IsMeasured() ) nGType = static_cast<OGRwkbGeometryType>(nGType | 0x40000000); } else if( eWkbVariant == wkbVariantIso ) nGType = getIsoGeometryType(); if( OGR_SWAP( eByteOrder ) ) { nGType = CPL_SWAP32(nGType); } memcpy( pabyData + 1, &nGType, 4 ); /* -------------------------------------------------------------------- */ /* Copy in the raw data. */ /* -------------------------------------------------------------------- */ if( OGR_SWAP( eByteOrder ) ) { const int nCount = CPL_SWAP32( oCC.nCurveCount ); memcpy( pabyData+5, &nCount, 4 ); } else { memcpy( pabyData+5, &oCC.nCurveCount, 4 ); } /* ==================================================================== */ /* Serialize each of the rings. */ /* ==================================================================== */ int nOffset = 9; for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ ) { OGRLinearRing* poLR = (OGRLinearRing*) oCC.papoCurves[iRing]; poLR->_exportToWkb( eByteOrder, flags, pabyData + nOffset ); nOffset += poLR->_WkbSize( flags ); } return OGRERR_NONE; }
//! @cond Doxygen_Suppress OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText, OGRwkbVariant eWkbVariant, const char* pszSkipPrefix ) const { size_t nCumulativeLength = 0; OGRErr eErr = OGRERR_NONE; bool bMustWriteComma = false; /* -------------------------------------------------------------------- */ /* Build a list of strings containing the stuff for each Geom. */ /* -------------------------------------------------------------------- */ char **papszGeoms = nGeomCount ? static_cast<char **>(CPLCalloc(sizeof(char *), nGeomCount)) : nullptr; for( int iGeom = 0; iGeom < nGeomCount; iGeom++ ) { eErr = papoGeoms[iGeom]->exportToWkt(&(papszGeoms[iGeom]), eWkbVariant); if( eErr != OGRERR_NONE ) goto error; size_t nSkip = 0; if( pszSkipPrefix != nullptr && EQUALN(papszGeoms[iGeom], pszSkipPrefix, strlen(pszSkipPrefix)) && papszGeoms[iGeom][strlen(pszSkipPrefix)] == ' ' ) { nSkip = strlen(pszSkipPrefix) + 1; if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "ZM ") ) nSkip += 3; else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "M ") ) nSkip += 2; if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") ) nSkip += 2; // Skip empty subgeoms. if( papszGeoms[iGeom][nSkip] != '(' ) { CPLDebug( "OGR", "OGRGeometryCollection::exportToWkt() - skipping %s.", papszGeoms[iGeom] ); CPLFree( papszGeoms[iGeom] ); papszGeoms[iGeom] = nullptr; continue; } } else if( eWkbVariant != wkbVariantIso ) { char *substr = nullptr; // TODO(schwehr): Looks dangerous. Cleanup. if( (substr = strstr(papszGeoms[iGeom], " Z")) != nullptr ) memmove(substr, substr + strlen(" Z"), 1 + strlen(substr + strlen(" Z"))); } nCumulativeLength += strlen(papszGeoms[iGeom] + nSkip); } /* -------------------------------------------------------------------- */ /* Return XXXXXXXXXXXXXXX EMPTY if we get no valid line string. */ /* -------------------------------------------------------------------- */ if( nCumulativeLength == 0 ) { CPLFree( papszGeoms ); CPLString osEmpty; if( eWkbVariant == wkbVariantIso ) { if( Is3D() && IsMeasured() ) osEmpty.Printf("%s ZM EMPTY", getGeometryName()); else if( IsMeasured() ) osEmpty.Printf("%s M EMPTY", getGeometryName()); else if( Is3D() ) osEmpty.Printf("%s Z EMPTY", getGeometryName()); else osEmpty.Printf("%s EMPTY", getGeometryName()); } else { osEmpty.Printf("%s EMPTY", getGeometryName()); } *ppszDstText = CPLStrdup(osEmpty); return OGRERR_NONE; } /* -------------------------------------------------------------------- */ /* Allocate the right amount of space for the aggregated string */ /* -------------------------------------------------------------------- */ *ppszDstText = static_cast<char *>( VSI_MALLOC_VERBOSE(nCumulativeLength + nGeomCount + 26)); if( *ppszDstText == nullptr ) { eErr = OGRERR_NOT_ENOUGH_MEMORY; goto error; } /* -------------------------------------------------------------------- */ /* Build up the string, freeing temporary strings as we go. */ /* -------------------------------------------------------------------- */ strcpy( *ppszDstText, getGeometryName() ); if( eWkbVariant == wkbVariantIso ) { if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) ) strcat( *ppszDstText, " ZM" ); else if( flags & OGR_G_3D ) strcat( *ppszDstText, " Z" ); else if( flags & OGR_G_MEASURED ) strcat( *ppszDstText, " M" ); } strcat( *ppszDstText, " (" ); nCumulativeLength = strlen(*ppszDstText); for( int iGeom = 0; iGeom < nGeomCount; iGeom++ ) { if( papszGeoms[iGeom] == nullptr ) continue; if( bMustWriteComma ) (*ppszDstText)[nCumulativeLength++] = ','; bMustWriteComma = true; size_t nSkip = 0; if( pszSkipPrefix != nullptr && EQUALN(papszGeoms[iGeom], pszSkipPrefix, strlen(pszSkipPrefix)) && papszGeoms[iGeom][strlen(pszSkipPrefix)] == ' ' ) { nSkip = strlen(pszSkipPrefix) + 1; if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "ZM ") ) nSkip += 3; else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "M ") ) nSkip += 2; else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") ) nSkip += 2; } const size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip); memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom] + nSkip, nGeomLength ); nCumulativeLength += nGeomLength; VSIFree( papszGeoms[iGeom] ); } (*ppszDstText)[nCumulativeLength++] = ')'; (*ppszDstText)[nCumulativeLength] = '\0'; CPLFree( papszGeoms ); return OGRERR_NONE; error: for( int iGeom = 0; iGeom < nGeomCount; iGeom++ ) CPLFree( papszGeoms[iGeom] ); CPLFree( papszGeoms ); return eErr; }
OGRErr OGRGeometryCollection::importFromWktInternal( const char ** ppszInput, int nRecLevel ) { // Arbitrary value, but certainly large enough for reasonable usages. if( nRecLevel == 32 ) { CPLError( CE_Failure, CPLE_AppDefined, "Too many recursion levels (%d) while parsing WKT geometry.", nRecLevel ); return OGRERR_CORRUPT_DATA; } int bHasZ = FALSE; int bHasM = FALSE; bool bIsEmpty = false; OGRErr eErr = importPreambleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty); if( eErr != OGRERR_NONE ) return eErr; if( bHasZ ) flags |= OGR_G_3D; if( bHasM ) flags |= OGR_G_MEASURED; if( bIsEmpty ) return OGRERR_NONE; char szToken[OGR_WKT_TOKEN_MAX] = {}; const char *pszInput = *ppszInput; // Skip first '('. pszInput = OGRWktReadToken( pszInput, szToken ); /* ==================================================================== */ /* Read each subgeometry in turn. */ /* ==================================================================== */ do { OGRGeometry *poGeom = nullptr; /* -------------------------------------------------------------------- */ /* Get the first token, which should be the geometry type. */ /* -------------------------------------------------------------------- */ OGRWktReadToken( pszInput, szToken ); /* -------------------------------------------------------------------- */ /* Do the import. */ /* -------------------------------------------------------------------- */ if( STARTS_WITH_CI(szToken, "GEOMETRYCOLLECTION") ) { OGRGeometryCollection* poGC = new OGRGeometryCollection(); poGeom = poGC; eErr = poGC->importFromWktInternal( &pszInput, nRecLevel + 1 ); } else eErr = OGRGeometryFactory::createFromWkt( &pszInput, nullptr, &poGeom ); if( eErr == OGRERR_NONE ) { // If this has M, but not Z, it is an error if poGeom does // not have M. if( !Is3D() && IsMeasured() && !poGeom->IsMeasured() ) eErr = OGRERR_CORRUPT_DATA; else eErr = addGeometryDirectly( poGeom ); } if( eErr != OGRERR_NONE ) { delete poGeom; return eErr; } /* -------------------------------------------------------------------- */ /* Read the delimiter following the ring. */ /* -------------------------------------------------------------------- */ pszInput = OGRWktReadToken( pszInput, szToken ); } while( szToken[0] == ',' ); /* -------------------------------------------------------------------- */ /* freak if we don't get a closing bracket. */ /* -------------------------------------------------------------------- */ if( szToken[0] != ')' ) return OGRERR_CORRUPT_DATA; *ppszInput = pszInput; return OGRERR_NONE; }
OGRErr OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder, unsigned char * pabyData, OGRwkbVariant eWkbVariant ) const { /* -------------------------------------------------------------------- */ /* Set the byte order. */ /* -------------------------------------------------------------------- */ pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER(static_cast<unsigned char>(eByteOrder)); pabyData += 1; /* -------------------------------------------------------------------- */ /* Set the geometry feature type. */ /* -------------------------------------------------------------------- */ GUInt32 nGType = getGeometryType(); if( eWkbVariant == wkbVariantPostGIS1 ) { nGType = wkbFlatten(nGType); if( Is3D() ) // Explicitly set wkb25DBit. nGType = static_cast<OGRwkbGeometryType>(nGType | wkb25DBitInternalUse); if( IsMeasured() ) nGType = static_cast<OGRwkbGeometryType>(nGType | 0x40000000); } else if( eWkbVariant == wkbVariantIso ) { nGType = getIsoGeometryType(); } if( eByteOrder == wkbNDR ) nGType = CPL_LSBWORD32( nGType ); else nGType = CPL_MSBWORD32( nGType ); memcpy( pabyData, &nGType, 4 ); pabyData += 4; /* -------------------------------------------------------------------- */ /* Copy in the raw data. Swap if needed. */ /* -------------------------------------------------------------------- */ if( IsEmpty() && eWkbVariant == wkbVariantIso ) { const double dNan = std::numeric_limits<double>::quiet_NaN(); memcpy( pabyData, &dNan, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); pabyData += 8; memcpy( pabyData, &dNan, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); pabyData += 8; if( flags & OGR_G_3D ) { memcpy( pabyData, &dNan, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); pabyData += 8; } if( flags & OGR_G_MEASURED ) { memcpy( pabyData, &dNan, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); } } else { memcpy( pabyData, &x, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); pabyData += 8; memcpy( pabyData, &y, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); pabyData += 8; if( flags & OGR_G_3D ) { memcpy( pabyData, &z, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); pabyData += 8; } if( flags & OGR_G_MEASURED ) { memcpy( pabyData, &m, 8 ); if( OGR_SWAP( eByteOrder ) ) CPL_SWAPDOUBLE( pabyData ); } } return OGRERR_NONE; }