char* GML_GetSRSName(const OGRSpatialReference* poSRS, int bLongSRS, int *pbCoordSwap) { *pbCoordSwap = FALSE; if (poSRS == NULL) return CPLStrdup(""); const char* pszAuthName = NULL; const char* pszAuthCode = NULL; const char* pszTarget = NULL; if (poSRS->IsProjected()) pszTarget = "PROJCS"; else pszTarget = "GEOGCS"; char szSrsName[50]; szSrsName[0] = 0; pszAuthName = poSRS->GetAuthorityName( pszTarget ); if( NULL != pszAuthName ) { if( EQUAL( pszAuthName, "EPSG" ) ) { pszAuthCode = poSRS->GetAuthorityCode( pszTarget ); if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 ) { if (bLongSRS && !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() || ((OGRSpatialReference*)poSRS)->EPSGTreatsAsNorthingEasting())) { OGRSpatialReference oSRS; if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE) { if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting()) *pbCoordSwap = TRUE; } } if (bLongSRS) { sprintf( szSrsName, " srsName=\"urn:ogc:def:crs:%s::%s\"", pszAuthName, pszAuthCode ); } else { sprintf( szSrsName, " srsName=\"%s:%s\"", pszAuthName, pszAuthCode ); } } } } return CPLStrdup(szSrsName); }
int GML_IsSRSLatLongOrder(const char* pszSRSName) { if (pszSRSName == NULL) return FALSE; if (strncmp(pszSRSName, "urn:", 4) == 0) { if (strstr(pszSRSName, ":4326") != NULL) { /* Shortcut ... */ return TRUE; } else { OGRSpatialReference oSRS; if (oSRS.importFromURN(pszSRSName) == OGRERR_NONE) { if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting()) return TRUE; } } } return FALSE; }
static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter, const swq_expr_node* poExpr, int bExpectBinary, ExprDumpFilterOptions* psOptions) { if( poExpr->eNodeType == SNT_COLUMN ) { if (bExpectBinary) return FALSE; /* Special fields not understood by server */ if (EQUAL(poExpr->string_value, "gml_id") || EQUAL(poExpr->string_value, "FID") || EQUAL(poExpr->string_value, "OGR_GEOMETRY") || EQUAL(poExpr->string_value, "OGR_GEOM_WKT") || EQUAL(poExpr->string_value, "OGR_GEOM_AREA") || EQUAL(poExpr->string_value, "OGR_STYLE")) { CPLDebug("WFS", "Attribute refers to a OGR special field. Cannot use server-side filtering"); return FALSE; } const char* pszFieldname = NULL; int nIndex; int bSameTable = psOptions->poFDefn != NULL && ( poExpr->table_name == NULL || EQUAL(poExpr->table_name, psOptions->poFDefn->GetName()) ); if( bSameTable ) { if( (nIndex = psOptions->poFDefn->GetFieldIndex(poExpr->string_value)) >= 0 ) { pszFieldname = psOptions->poFDefn->GetFieldDefn(nIndex)->GetNameRef(); } else if( (nIndex = psOptions->poFDefn->GetGeomFieldIndex(poExpr->string_value)) >= 0 ) { pszFieldname = psOptions->poFDefn->GetGeomFieldDefn(nIndex)->GetNameRef(); } } else if( psOptions->poDS != NULL ) { OGRLayer* poLayer = psOptions->poDS->GetLayerByName(poExpr->table_name); if( poLayer ) { OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn(); if( (nIndex = poFDefn->GetFieldIndex(poExpr->string_value)) >= 0 ) { pszFieldname = CPLSPrintf("%s/%s", poLayer->GetName(), poFDefn->GetFieldDefn(nIndex)->GetNameRef()); } else if( (nIndex = poFDefn->GetGeomFieldIndex(poExpr->string_value)) >= 0 ) { pszFieldname = CPLSPrintf("%s/%s", poLayer->GetName(), poFDefn->GetGeomFieldDefn(nIndex)->GetNameRef()); } } } if( psOptions->poFDefn == NULL && psOptions->poDS == NULL ) pszFieldname = poExpr->string_value; if( pszFieldname == NULL ) { if( poExpr->table_name != NULL ) CPLDebug("WFS", "Field \"%s\".\"%s\" unknown. Cannot use server-side filtering", poExpr->table_name, poExpr->string_value); else CPLDebug("WFS", "Field \"%s\" unknown. Cannot use server-side filtering", poExpr->string_value); return FALSE; } if (psOptions->nVersion >= 200) osFilter += CPLSPrintf("<%sValueReference>", psOptions->pszNSPrefix); else osFilter += CPLSPrintf("<%sPropertyName>", psOptions->pszNSPrefix); char* pszFieldnameXML = CPLEscapeString(pszFieldname, -1, CPLES_XML); osFilter += pszFieldnameXML; CPLFree(pszFieldnameXML); if (psOptions->nVersion >= 200) osFilter += CPLSPrintf("</%sValueReference>", psOptions->pszNSPrefix); else osFilter += CPLSPrintf("</%sPropertyName>", psOptions->pszNSPrefix); return TRUE; } if( poExpr->eNodeType == SNT_CONSTANT ) { if (bExpectBinary) return FALSE; osFilter += CPLSPrintf("<%sLiteral>", psOptions->pszNSPrefix); if( !WFS_ExprDumpRawLitteral(osFilter, poExpr) ) return FALSE; osFilter += CPLSPrintf("</%sLiteral>", psOptions->pszNSPrefix); return TRUE; } if( poExpr->eNodeType != SNT_OPERATION ) return FALSE; /* shouldn't happen */ if( poExpr->nOperation == SWQ_NOT ) { osFilter += CPLSPrintf("<%sNot>", psOptions->pszNSPrefix); if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], TRUE, psOptions)) return FALSE; osFilter += CPLSPrintf("</%sNot>", psOptions->pszNSPrefix); return TRUE; } if( poExpr->nOperation == SWQ_LIKE ) { CPLString osVal; char ch; char firstCh = 0; int i; if (psOptions->nVersion == 100) osFilter += CPLSPrintf("<%sPropertyIsLike wildCard='*' singleChar='_' escape='!'>", psOptions->pszNSPrefix); else osFilter += CPLSPrintf("<%sPropertyIsLike wildCard='*' singleChar='_' escapeChar='!'>", psOptions->pszNSPrefix); if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions)) return FALSE; if (poExpr->papoSubExpr[1]->eNodeType != SNT_CONSTANT && poExpr->papoSubExpr[1]->field_type != SWQ_STRING) return FALSE; osFilter += CPLSPrintf("<%sLiteral>", psOptions->pszNSPrefix); /* Escape value according to above special characters */ /* For URL compatibility reason, we remap the OGR SQL '%' wildchard into '*' */ i = 0; ch = poExpr->papoSubExpr[1]->string_value[i]; if (ch == '\'' || ch == '"') { firstCh = ch; i ++; } for(;(ch = poExpr->papoSubExpr[1]->string_value[i]) != '\0';i++) { if (ch == '%') osVal += "*"; else if (ch == '!') osVal += "!!"; else if (ch == '*') osVal += "!*"; else if (ch == firstCh && poExpr->papoSubExpr[1]->string_value[i + 1] == 0) break; else { char ach[2]; ach[0] = ch; ach[1] = 0; osVal += ach; } } char* pszXML = CPLEscapeString(osVal, -1, CPLES_XML); osFilter += pszXML; CPLFree(pszXML); osFilter += CPLSPrintf("</%sLiteral>", psOptions->pszNSPrefix); osFilter += CPLSPrintf("</%sPropertyIsLike>", psOptions->pszNSPrefix); return TRUE; } if( poExpr->nOperation == SWQ_ISNULL ) { osFilter += CPLSPrintf("<%sPropertyIsNull>", psOptions->pszNSPrefix); if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions)) return FALSE; osFilter += CPLSPrintf("</%sPropertyIsNull>", psOptions->pszNSPrefix); psOptions->bOutNeedsNullCheck = TRUE; return TRUE; } if( poExpr->nOperation == SWQ_EQ || poExpr->nOperation == SWQ_NE || poExpr->nOperation == SWQ_LE || poExpr->nOperation == SWQ_LT || poExpr->nOperation == SWQ_GE || poExpr->nOperation == SWQ_GT ) { int nOperation = poExpr->nOperation; int bAddClosingNot = FALSE; if (!psOptions->bPropertyIsNotEqualToSupported && nOperation == SWQ_NE) { osFilter += CPLSPrintf("<%sNot>", psOptions->pszNSPrefix); nOperation = SWQ_EQ; bAddClosingNot = TRUE; } const char* pszName = NULL; switch(nOperation) { case SWQ_EQ: pszName = "PropertyIsEqualTo"; break; case SWQ_NE: pszName = "PropertyIsNotEqualTo"; break; case SWQ_LE: pszName = "PropertyIsLessThanOrEqualTo"; break; case SWQ_LT: pszName = "PropertyIsLessThan"; break; case SWQ_GE: pszName = "PropertyIsGreaterThanOrEqualTo"; break; case SWQ_GT: pszName = "PropertyIsGreaterThan"; break; default: break; } osFilter += "<"; osFilter += psOptions->pszNSPrefix; osFilter += pszName; osFilter += ">"; if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions)) return FALSE; if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[1], FALSE, psOptions)) return FALSE; osFilter += "</"; osFilter += psOptions->pszNSPrefix; osFilter += pszName; osFilter += ">"; if (bAddClosingNot) osFilter += CPLSPrintf("</%sNot>", psOptions->pszNSPrefix); return TRUE; } if( poExpr->nOperation == SWQ_AND || poExpr->nOperation == SWQ_OR ) { const char* pszName = (poExpr->nOperation == SWQ_AND) ? "And" : "Or"; osFilter += "<"; osFilter += psOptions->pszNSPrefix; osFilter += pszName; osFilter += ">"; if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], TRUE, psOptions)) return FALSE; if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[1], TRUE, psOptions)) return FALSE; osFilter += "</"; osFilter += psOptions->pszNSPrefix; osFilter += pszName; osFilter += ">"; return TRUE; } if( poExpr->nOperation == SWQ_CUSTOM_FUNC && EQUAL(poExpr->string_value, "ST_MakeEnvelope") ) { OGRSpatialReference oSRS; const char* pszSRSName = WFS_ExprGetSRSName( poExpr, 4, psOptions, oSRS ); int bAxisSwap = FALSE; osFilter += "<gml:Envelope"; if( pszSRSName ) { osFilter += " srsName=\""; osFilter += pszSRSName; osFilter += "\""; if( oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting() ) bAxisSwap = TRUE; } osFilter += ">"; osFilter += "<gml:lowerCorner>"; if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 1 : 0])) return FALSE; osFilter += " "; if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 0 : 1])) return FALSE; osFilter += "</gml:lowerCorner>"; osFilter += "<gml:upperCorner>"; if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 3 : 2])) return FALSE; osFilter += " "; if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 2 : 3])) return FALSE; osFilter += "</gml:upperCorner>"; osFilter += "</gml:Envelope>"; return TRUE; } if( poExpr->nOperation == SWQ_CUSTOM_FUNC && EQUAL(poExpr->string_value, "ST_GeomFromText") ) { OGRSpatialReference oSRS; const char* pszSRSName = WFS_ExprGetSRSName( poExpr, 1, psOptions, oSRS ); OGRGeometry* poGeom = NULL; char* pszWKT = (char*)poExpr->papoSubExpr[0]->string_value; OGRGeometryFactory::createFromWkt(&pszWKT, NULL, &poGeom); char** papszOptions = NULL; papszOptions = CSLSetNameValue(papszOptions, "FORMAT", "GML3"); if( pszSRSName != NULL ) { if( oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting() ) { OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode( "GEOGCS" ); if( poGEOGCS != NULL ) poGEOGCS->StripNodes( "AXIS" ); OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" ); if (poPROJCS != NULL && oSRS.EPSGTreatsAsNorthingEasting()) poPROJCS->StripNodes( "AXIS" ); } if( EQUALN(pszSRSName, "urn:ogc:def:crs:EPSG::", strlen("urn:ogc:def:crs:EPSG::")) ) papszOptions = CSLSetNameValue(papszOptions, "GML3_LONGSRS", "YES"); else papszOptions = CSLSetNameValue(papszOptions, "GML3_LONGSRS", "NO"); poGeom->assignSpatialReference(&oSRS); } papszOptions = CSLSetNameValue(papszOptions, "GMLID", CPLSPrintf("id%d", psOptions->nUniqueGeomGMLId ++)); char* pszGML = OGR_G_ExportToGMLEx( (OGRGeometryH)poGeom, papszOptions ); osFilter += pszGML; CSLDestroy(papszOptions); delete poGeom; CPLFree(pszGML); return TRUE; } if( poExpr->nOperation == SWQ_CUSTOM_FUNC ) { const char* pszName = EQUAL(poExpr->string_value, "ST_Equals") ? "Equals" : EQUAL(poExpr->string_value, "ST_Disjoint") ? "Disjoint" : EQUAL(poExpr->string_value, "ST_Touches") ? "Touches" : EQUAL(poExpr->string_value, "ST_Contains") ? "Contains" : EQUAL(poExpr->string_value, "ST_Intersects") ? "Intersects" : EQUAL(poExpr->string_value, "ST_Within") ? "Within" : EQUAL(poExpr->string_value, "ST_Crosses") ? "Crosses" : EQUAL(poExpr->string_value, "ST_Overlaps") ? "Overlaps" : EQUAL(poExpr->string_value, "ST_DWithin") ? "DWithin" : EQUAL(poExpr->string_value, "ST_Beyond") ? "Beyond" : NULL; if( pszName == NULL ) return FALSE; osFilter += "<"; osFilter += psOptions->pszNSPrefix; osFilter += pszName; osFilter += ">"; for(int i=0;i<2;i++) { if( i == 1 && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN && poExpr->papoSubExpr[1]->eNodeType == SNT_OPERATION && poExpr->papoSubExpr[1]->nOperation == SWQ_CUSTOM_FUNC && (EQUAL(poExpr->papoSubExpr[1]->string_value, "ST_GeomFromText") || EQUAL(poExpr->papoSubExpr[1]->string_value, "ST_MakeEnvelope")) ) { int bSameTable = psOptions->poFDefn != NULL && ( poExpr->papoSubExpr[0]->table_name == NULL || EQUAL(poExpr->papoSubExpr[0]->table_name, psOptions->poFDefn->GetName()) ); if( bSameTable ) { int nIndex; if( (nIndex = psOptions->poFDefn->GetGeomFieldIndex(poExpr->papoSubExpr[0]->string_value)) >= 0 ) { psOptions->poSRS = psOptions->poFDefn->GetGeomFieldDefn(nIndex)->GetSpatialRef(); } } else if( psOptions->poDS != NULL ) { OGRLayer* poLayer = psOptions->poDS->GetLayerByName(poExpr->papoSubExpr[0]->table_name); if( poLayer ) { OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn(); int nIndex; if( (nIndex = poFDefn->GetGeomFieldIndex(poExpr->papoSubExpr[0]->string_value)) >= 0 ) { psOptions->poSRS = poFDefn->GetGeomFieldDefn(nIndex)->GetSpatialRef(); } } } } int bRet = WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[i], FALSE, psOptions); psOptions->poSRS = NULL; if( !bRet ) return FALSE; } if( poExpr->nSubExprCount > 2 ) { osFilter += CPLSPrintf("<%sDistance unit=\"m\">", psOptions->pszNSPrefix); if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[2]) ) return FALSE; osFilter += CPLSPrintf("</%sDistance>", psOptions->pszNSPrefix); } osFilter += "</"; osFilter += psOptions->pszNSPrefix; osFilter += pszName; osFilter += ">"; return TRUE; } return FALSE; }
static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry, const OGRSpatialReference* poParentSRS, char **ppszText, int *pnLength, int *pnMaxLength, int bIsSubGeometry, int bLongSRS, int bLineStringAsCurve, const char* pszGMLId = NULL) { /* -------------------------------------------------------------------- */ /* Check for Spatial Reference System attached to given geometry */ /* -------------------------------------------------------------------- */ // Buffer for srsName and gml:id attributes (srsName="..." gml:id="...") char szAttributes[256]; int nAttrsLength = 0; szAttributes[0] = 0; const OGRSpatialReference* poSRS = NULL; if (poParentSRS) poSRS = poParentSRS; else poParentSRS = poSRS = poGeometry->getSpatialReference(); int bCoordSwap = FALSE; if( NULL != poSRS ) { const char* pszAuthName = NULL; const char* pszAuthCode = NULL; const char* pszTarget = NULL; if (poSRS->IsProjected()) pszTarget = "PROJCS"; else pszTarget = "GEOGCS"; pszAuthName = poSRS->GetAuthorityName( pszTarget ); if( NULL != pszAuthName ) { if( EQUAL( pszAuthName, "EPSG" ) ) { pszAuthCode = poSRS->GetAuthorityCode( pszTarget ); if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 ) { if (bLongSRS && !((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong()) { OGRSpatialReference oSRS; if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE) { if (oSRS.EPSGTreatsAsLatLong()) bCoordSwap = TRUE; } } if (!bIsSubGeometry) { if (bLongSRS) { snprintf( szAttributes, sizeof(szAttributes), " srsName=\"urn:ogc:def:crs:%s::%s\"", pszAuthName, pszAuthCode ); } else { snprintf( szAttributes, sizeof(szAttributes), " srsName=\"%s:%s\"", pszAuthName, pszAuthCode ); } nAttrsLength = strlen(szAttributes); } } } } } if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes)) { strcat(szAttributes, " gml:id=\""); strcat(szAttributes, pszGMLId); strcat(szAttributes, "\""); nAttrsLength = strlen(szAttributes); } /* -------------------------------------------------------------------- */ /* 2D Point */ /* -------------------------------------------------------------------- */ if( poGeometry->getGeometryType() == wkbPoint ) { char szCoordinate[256]; OGRPoint *poPoint = (OGRPoint *) poGeometry; if (bCoordSwap) OGRMakeWktCoordinate( szCoordinate, poPoint->getY(), poPoint->getX(), 0.0, 2 ); else OGRMakeWktCoordinate( szCoordinate, poPoint->getX(), poPoint->getY(), 0.0, 2 ); _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength, ppszText, pnMaxLength ); sprintf( *ppszText + *pnLength, "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>", szAttributes, szCoordinate ); *pnLength += strlen( *ppszText + *pnLength ); } /* -------------------------------------------------------------------- */ /* 3D Point */ /* -------------------------------------------------------------------- */ else if( poGeometry->getGeometryType() == wkbPoint25D ) { char szCoordinate[256]; OGRPoint *poPoint = (OGRPoint *) poGeometry; if (bCoordSwap) OGRMakeWktCoordinate( szCoordinate, poPoint->getY(), poPoint->getX(), poPoint->getZ(), 3 ); else OGRMakeWktCoordinate( szCoordinate, poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 ); _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength, ppszText, pnMaxLength ); sprintf( *ppszText + *pnLength, "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>", szAttributes, szCoordinate ); *pnLength += strlen( *ppszText + *pnLength ); } /* -------------------------------------------------------------------- */ /* LineString and LinearRing */ /* -------------------------------------------------------------------- */ else if( poGeometry->getGeometryType() == wkbLineString || poGeometry->getGeometryType() == wkbLineString25D ) { int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING"); if (!bRing && bLineStringAsCurve) { AppendString( ppszText, pnLength, pnMaxLength, "<gml:Curve" ); AppendString( ppszText, pnLength, pnMaxLength, szAttributes ); AppendString( ppszText, pnLength, pnMaxLength, "><gml:segments><gml:LineStringSegment>" ); AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap, ppszText, pnLength, pnMaxLength ); AppendString( ppszText, pnLength, pnMaxLength, "</gml:LineStringSegment></gml:segments></gml:Curve>" ); } else { // Buffer for tag name + srsName attribute if set const size_t nLineTagLength = 16; char* pszLineTagName = NULL; pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 ); if( bRing ) { /* LinearRing isn't supposed to have srsName attribute according to GML3 SF-0 */ AppendString( ppszText, pnLength, pnMaxLength, "<gml:LinearRing>" ); } else { sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes ); AppendString( ppszText, pnLength, pnMaxLength, pszLineTagName ); } // FREE TAG BUFFER CPLFree( pszLineTagName ); AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap, ppszText, pnLength, pnMaxLength ); if( bRing ) AppendString( ppszText, pnLength, pnMaxLength, "</gml:LinearRing>" ); else AppendString( ppszText, pnLength, pnMaxLength, "</gml:LineString>" ); } } /* -------------------------------------------------------------------- */ /* Polygon */ /* -------------------------------------------------------------------- */ else if( poGeometry->getGeometryType() == wkbPolygon || poGeometry->getGeometryType() == wkbPolygon25D ) { OGRPolygon *poPolygon = (OGRPolygon *) poGeometry; // Buffer for polygon tag name + srsName attribute if set const size_t nPolyTagLength = 13; char* pszPolyTagName = NULL; pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 ); // Compose Polygon tag with or without srsName attribute sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes ); AppendString( ppszText, pnLength, pnMaxLength, pszPolyTagName ); // FREE TAG BUFFER CPLFree( pszPolyTagName ); // Don't add srsName to polygon rings if( poPolygon->getExteriorRing() != NULL ) { AppendString( ppszText, pnLength, pnMaxLength, "<gml:exterior>" ); if( !OGR2GML3GeometryAppend( poPolygon->getExteriorRing(), poSRS, ppszText, pnLength, pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve ) ) { return FALSE; } AppendString( ppszText, pnLength, pnMaxLength, "</gml:exterior>" ); } for( int iRing = 0; iRing < poPolygon->getNumInteriorRings(); iRing++ ) { OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing); AppendString( ppszText, pnLength, pnMaxLength, "<gml:interior>" ); if( !OGR2GML3GeometryAppend( poRing, poSRS, ppszText, pnLength, pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve ) ) return FALSE; AppendString( ppszText, pnLength, pnMaxLength, "</gml:interior>" ); } AppendString( ppszText, pnLength, pnMaxLength, "</gml:Polygon>" ); } /* -------------------------------------------------------------------- */ /* MultiPolygon, MultiLineString, MultiPoint, MultiGeometry */ /* -------------------------------------------------------------------- */ else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection ) { OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry; int iMember; const char *pszElemClose = NULL; const char *pszMemberElem = NULL; // Buffer for opening tag + srsName attribute char* pszElemOpen = NULL; if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon ) { pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiSurface%s>", szAttributes ); pszElemClose = "MultiSurface>"; pszMemberElem = "surfaceMember>"; } else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString ) { pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiCurve%s>", szAttributes ); pszElemClose = "MultiCurve>"; pszMemberElem = "curveMember>"; } else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint ) { pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiPoint%s>", szAttributes ); pszElemClose = "MultiPoint>"; pszMemberElem = "pointMember>"; } else { pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes ); pszElemClose = "MultiGeometry>"; pszMemberElem = "geometryMember>"; } AppendString( ppszText, pnLength, pnMaxLength, "<gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen ); for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++) { OGRGeometry *poMember = poGC->getGeometryRef( iMember ); AppendString( ppszText, pnLength, pnMaxLength, "<gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem ); if( !OGR2GML3GeometryAppend( poMember, poSRS, ppszText, pnLength, pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve ) ) { return FALSE; } AppendString( ppszText, pnLength, pnMaxLength, "</gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem ); } AppendString( ppszText, pnLength, pnMaxLength, "</gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszElemClose ); // FREE TAG BUFFER CPLFree( pszElemOpen ); } else { return FALSE; } return TRUE; }
static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry, const OGRSpatialReference* poParentSRS, char **ppszText, int *pnLength, int *pnMaxLength, int bIsSubGeometry, int bLongSRS, int bLineStringAsCurve, const char* pszGMLId, int nSRSDimensionLocFlags, int bForceLineStringAsLinearRing ) { /* -------------------------------------------------------------------- */ /* Check for Spatial Reference System attached to given geometry */ /* -------------------------------------------------------------------- */ // Buffer for srsName, srsDimension and gml:id attributes (srsName="..." gml:id="...") char szAttributes[256]; int nAttrsLength = 0; szAttributes[0] = 0; const OGRSpatialReference* poSRS = NULL; if (poParentSRS) poSRS = poParentSRS; else poParentSRS = poSRS = poGeometry->getSpatialReference(); int bCoordSwap = FALSE; if( NULL != poSRS ) { const char* pszAuthName = NULL; const char* pszAuthCode = NULL; const char* pszTarget = NULL; if (poSRS->IsProjected()) pszTarget = "PROJCS"; else pszTarget = "GEOGCS"; pszAuthName = poSRS->GetAuthorityName( pszTarget ); if( NULL != pszAuthName ) { if( EQUAL( pszAuthName, "EPSG" ) ) { pszAuthCode = poSRS->GetAuthorityCode( pszTarget ); if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 ) { if (bLongSRS && !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() || ((OGRSpatialReference*)poSRS)->EPSGTreatsAsNorthingEasting())) { OGRSpatialReference oSRS; if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE) { if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting()) bCoordSwap = TRUE; } } if (!bIsSubGeometry) { if (bLongSRS) { snprintf( szAttributes, sizeof(szAttributes), " srsName=\"urn:ogc:def:crs:%s::%s\"", pszAuthName, pszAuthCode ); } else { snprintf( szAttributes, sizeof(szAttributes), " srsName=\"%s:%s\"", pszAuthName, pszAuthCode ); } nAttrsLength = strlen(szAttributes); } } } } } if( (nSRSDimensionLocFlags & SRSDIM_LOC_GEOMETRY) != 0 && wkbHasZ(poGeometry->getGeometryType()) ) { strcat(szAttributes, " srsDimension=\"3\""); nAttrsLength = strlen(szAttributes); nSRSDimensionLocFlags &= ~SRSDIM_LOC_GEOMETRY; } if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes)) { strcat(szAttributes, " gml:id=\""); strcat(szAttributes, pszGMLId); strcat(szAttributes, "\""); nAttrsLength = strlen(szAttributes); } OGRwkbGeometryType eType = poGeometry->getGeometryType(); OGRwkbGeometryType eFType = wkbFlatten(eType); /* -------------------------------------------------------------------- */ /* 2D Point */ /* -------------------------------------------------------------------- */ if( eType == wkbPoint ) { char szCoordinate[256]; OGRPoint *poPoint = (OGRPoint *) poGeometry; if (bCoordSwap) OGRMakeWktCoordinate( szCoordinate, poPoint->getY(), poPoint->getX(), 0.0, 2 ); else OGRMakeWktCoordinate( szCoordinate, poPoint->getX(), poPoint->getY(), 0.0, 2 ); _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength, ppszText, pnMaxLength ); sprintf( *ppszText + *pnLength, "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>", szAttributes, szCoordinate ); *pnLength += strlen( *ppszText + *pnLength ); } /* -------------------------------------------------------------------- */ /* 3D Point */ /* -------------------------------------------------------------------- */ else if( eType == wkbPoint25D ) { char szCoordinate[256]; OGRPoint *poPoint = (OGRPoint *) poGeometry; if (bCoordSwap) OGRMakeWktCoordinate( szCoordinate, poPoint->getY(), poPoint->getX(), poPoint->getZ(), 3 ); else OGRMakeWktCoordinate( szCoordinate, poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 ); _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength, ppszText, pnMaxLength ); sprintf( *ppszText + *pnLength, "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>", szAttributes, szCoordinate ); *pnLength += strlen( *ppszText + *pnLength ); } /* -------------------------------------------------------------------- */ /* LineString and LinearRing */ /* -------------------------------------------------------------------- */ else if( eFType == wkbLineString ) { int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING") || bForceLineStringAsLinearRing; if (!bRing && bLineStringAsCurve) { AppendString( ppszText, pnLength, pnMaxLength, "<gml:Curve" ); AppendString( ppszText, pnLength, pnMaxLength, szAttributes ); AppendString( ppszText, pnLength, pnMaxLength, "><gml:segments><gml:LineStringSegment>" ); AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap, ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags ); AppendString( ppszText, pnLength, pnMaxLength, "</gml:LineStringSegment></gml:segments></gml:Curve>" ); } else { // Buffer for tag name + srsName attribute if set const size_t nLineTagLength = 16; char* pszLineTagName = NULL; pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 ); if( bRing ) { /* LinearRing isn't supposed to have srsName attribute according to GML3 SF-0 */ AppendString( ppszText, pnLength, pnMaxLength, "<gml:LinearRing>" ); } else { sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes ); AppendString( ppszText, pnLength, pnMaxLength, pszLineTagName ); } // FREE TAG BUFFER CPLFree( pszLineTagName ); AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap, ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags ); if( bRing ) AppendString( ppszText, pnLength, pnMaxLength, "</gml:LinearRing>" ); else AppendString( ppszText, pnLength, pnMaxLength, "</gml:LineString>" ); } } /* -------------------------------------------------------------------- */ /* ArcString or Circle */ /* -------------------------------------------------------------------- */ else if( eFType == wkbCircularString ) { AppendString( ppszText, pnLength, pnMaxLength, "<gml:Curve" ); AppendString( ppszText, pnLength, pnMaxLength, szAttributes ); OGRSimpleCurve* poSC = (OGRSimpleCurve *) poGeometry; /* SQL MM has a unique type for arc and circle, GML not */ if( poSC->getNumPoints() == 3 && poSC->getX(0) == poSC->getX(2) && poSC->getY(0) == poSC->getY(2) ) { double dfMidX = (poSC->getX(0) + poSC->getX(1)) / 2; double dfMidY = (poSC->getY(0) + poSC->getY(1)) / 2; double dfDirX = (poSC->getX(1) - poSC->getX(0)) / 2; double dfDirY = (poSC->getY(1) - poSC->getY(0)) / 2; double dfNormX = -dfDirY; double dfNormY = dfDirX; double dfNewX = dfMidX + dfNormX; double dfNewY = dfMidY + dfNormY; OGRLineString* poLS = new OGRLineString(); OGRPoint p; poSC->getPoint(0, &p); poLS->addPoint(&p); poSC->getPoint(1, &p); if( poSC->getCoordinateDimension() == 3 ) poLS->addPoint(dfNewX, dfNewY, p.getZ()); else poLS->addPoint(dfNewX, dfNewY); poLS->addPoint(&p); AppendString( ppszText, pnLength, pnMaxLength, "><gml:segments><gml:Circle>" ); AppendGML3CoordinateList( poLS, bCoordSwap, ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags ); AppendString( ppszText, pnLength, pnMaxLength, "</gml:Circle></gml:segments></gml:Curve>" ); delete poLS; } else { AppendString( ppszText, pnLength, pnMaxLength, "><gml:segments><gml:ArcString>" ); AppendGML3CoordinateList( poSC, bCoordSwap, ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags ); AppendString( ppszText, pnLength, pnMaxLength, "</gml:ArcString></gml:segments></gml:Curve>" ); } } /* -------------------------------------------------------------------- */ /* CompositeCurve */ /* -------------------------------------------------------------------- */ else if( eFType == wkbCompoundCurve ) { AppendString( ppszText, pnLength, pnMaxLength, "<gml:CompositeCurve" ); AppendString( ppszText, pnLength, pnMaxLength, szAttributes ); AppendString( ppszText, pnLength, pnMaxLength,">"); OGRCompoundCurve* poCC = (OGRCompoundCurve*)poGeometry; for(int i=0;i<poCC->getNumCurves();i++) { AppendString( ppszText, pnLength, pnMaxLength, "<gml:curveMember>" ); if( !OGR2GML3GeometryAppend( poCC->getCurve(i), poSRS, ppszText, pnLength, pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve, NULL, nSRSDimensionLocFlags, FALSE) ) return FALSE; AppendString( ppszText, pnLength, pnMaxLength, "</gml:curveMember>" ); } AppendString( ppszText, pnLength, pnMaxLength, "</gml:CompositeCurve>" ); } /* -------------------------------------------------------------------- */ /* Polygon */ /* -------------------------------------------------------------------- */ else if( eFType == wkbPolygon || eFType == wkbCurvePolygon ) { OGRCurvePolygon *poCP = (OGRCurvePolygon *) poGeometry; // Buffer for polygon tag name + srsName attribute if set const size_t nPolyTagLength = 13; char* pszPolyTagName = NULL; pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 ); // Compose Polygon tag with or without srsName attribute sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes ); AppendString( ppszText, pnLength, pnMaxLength, pszPolyTagName ); // FREE TAG BUFFER CPLFree( pszPolyTagName ); // Don't add srsName to polygon rings if( poCP->getExteriorRingCurve() != NULL ) { AppendString( ppszText, pnLength, pnMaxLength, "<gml:exterior>" ); if( !OGR2GML3GeometryAppend( poCP->getExteriorRingCurve(), poSRS, ppszText, pnLength, pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve, NULL, nSRSDimensionLocFlags, TRUE) ) { return FALSE; } AppendString( ppszText, pnLength, pnMaxLength, "</gml:exterior>" ); } for( int iRing = 0; iRing < poCP->getNumInteriorRings(); iRing++ ) { OGRCurve *poRing = poCP->getInteriorRingCurve(iRing); AppendString( ppszText, pnLength, pnMaxLength, "<gml:interior>" ); if( !OGR2GML3GeometryAppend( poRing, poSRS, ppszText, pnLength, pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve, NULL, nSRSDimensionLocFlags, TRUE) ) return FALSE; AppendString( ppszText, pnLength, pnMaxLength, "</gml:interior>" ); } AppendString( ppszText, pnLength, pnMaxLength, "</gml:Polygon>" ); } /* -------------------------------------------------------------------- */ /* MultiSurface, MultiCurve, MultiPoint, MultiGeometry */ /* -------------------------------------------------------------------- */ else if( eFType == wkbMultiPolygon || eFType == wkbMultiSurface || eFType == wkbMultiLineString || eFType == wkbMultiCurve || eFType == wkbMultiPoint || eFType == wkbGeometryCollection ) { OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry; int iMember; const char *pszElemClose = NULL; const char *pszMemberElem = NULL; // Buffer for opening tag + srsName attribute char* pszElemOpen = NULL; if( eFType == wkbMultiPolygon || eFType == wkbMultiSurface ) { pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiSurface%s>", szAttributes ); pszElemClose = "MultiSurface>"; pszMemberElem = "surfaceMember>"; } else if( eFType == wkbMultiLineString || eFType == wkbMultiCurve ) { pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiCurve%s>", szAttributes ); pszElemClose = "MultiCurve>"; pszMemberElem = "curveMember>"; } else if( eFType == wkbMultiPoint ) { pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiPoint%s>", szAttributes ); pszElemClose = "MultiPoint>"; pszMemberElem = "pointMember>"; } else { pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 ); sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes ); pszElemClose = "MultiGeometry>"; pszMemberElem = "geometryMember>"; } AppendString( ppszText, pnLength, pnMaxLength, "<gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen ); for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++) { OGRGeometry *poMember = poGC->getGeometryRef( iMember ); AppendString( ppszText, pnLength, pnMaxLength, "<gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem ); char* pszGMLIdSub = NULL; if (pszGMLId != NULL) pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember)); if( !OGR2GML3GeometryAppend( poMember, poSRS, ppszText, pnLength, pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve, pszGMLIdSub, nSRSDimensionLocFlags, FALSE ) ) { CPLFree(pszGMLIdSub); return FALSE; } CPLFree(pszGMLIdSub); AppendString( ppszText, pnLength, pnMaxLength, "</gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem ); } AppendString( ppszText, pnLength, pnMaxLength, "</gml:" ); AppendString( ppszText, pnLength, pnMaxLength, pszElemClose ); // FREE TAG BUFFER CPLFree( pszElemOpen ); } else { CPLError(CE_Failure, CPLE_NotSupported, "Unsupported geometry type %s", OGRGeometryTypeToName(eType)); return FALSE; } return TRUE; }