void OGRJMLWriterLayer::WriteColumnDeclaration( const char* pszName, const char* pszType ) { char* pszEscapedName = OGRGetXML_UTF8_EscapedString( pszName ); if( bClassicGML ) { VSIFPrintfL(fp, " <column>\n" " <name>%s</name>\n" " <type>%s</type>\n" " <valueElement elementName=\"%s\"/>\n" " <valueLocation position=\"body\"/>\n" " </column>\n", pszEscapedName, pszType, pszEscapedName); } else { VSIFPrintfL(fp, " <column>\n" " <name>%s</name>\n" " <type>%s</type>\n" " <valueElement elementName=\"property\" attributeName=\"name\" attributeValue=\"%s\"/>\n" " <valueLocation position=\"body\"/>\n" " </column>\n", pszEscapedName, pszType, pszEscapedName); } CPLFree(pszEscapedName); }
OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature ) { /* Finish column declaration if we haven't yet created a feature */ if( !bFeaturesWritten ) { if( bAddOGRStyleField && poFeatureDefn->GetFieldIndex("OGR_STYLE") < 0 ) { WriteColumnDeclaration( "OGR_STYLE", "STRING" ); } if( bAddRGBField && poFeatureDefn->GetFieldIndex("R_G_B") < 0 ) { WriteColumnDeclaration( "R_G_B", "STRING" ); } VSIFPrintfL(fp, "</ColumnDefinitions>\n</JCSGMLInputTemplate>\n<featureCollection>\n"); bFeaturesWritten = TRUE; } if( bClassicGML ) VSIFPrintfL(fp, " <featureMember>\n"); VSIFPrintfL(fp, " <feature>\n"); /* Add geometry */ VSIFPrintfL(fp, " <geometry>\n"); OGRGeometry* poGeom = poFeature->GetGeometryRef(); if( poGeom != NULL ) { char* pszGML = poGeom->exportToGML(); VSIFPrintfL(fp, " %s\n", pszGML); CPLFree(pszGML); } else { VSIFPrintfL(fp, " %s\n", "<gml:MultiGeometry></gml:MultiGeometry>"); } VSIFPrintfL(fp, " </geometry>\n"); /* Add fields */ for(int i=0;i<poFeature->GetFieldCount();i++) { char* pszName = OGRGetXML_UTF8_EscapedString( poFeatureDefn->GetFieldDefn(i)->GetNameRef() ); if( bClassicGML ) VSIFPrintfL(fp, " <%s>", pszName); else VSIFPrintfL(fp, " <property name=\"%s\">", pszName); if( poFeature->IsFieldSet(i) ) { OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType(); if( eType == OFTString ) { char* pszValue = OGRGetXML_UTF8_EscapedString( poFeature->GetFieldAsString(i) ); VSIFPrintfL(fp, "%s", pszValue); CPLFree(pszValue); } else if( eType == OFTDateTime ) { int nYear, nMonth, nDay, nHour, nMinute, nTZFlag; float fSecond; poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZFlag); /* When writing time zone, OpenJUMP expects .XXX seconds */ /* to be written */ if( nTZFlag > 1 || OGR_GET_MS(fSecond) != 0 ) VSIFPrintfL(fp, "%04d-%02d-%02dT%02d:%02d:%06.3f", nYear, nMonth, nDay, nHour, nMinute, fSecond); else VSIFPrintfL(fp, "%04d-%02d-%02dT%02d:%02d:%02d", nYear, nMonth, nDay, nHour, nMinute, (int)fSecond); if( nTZFlag > 1 ) { int nOffset = (nTZFlag - 100) * 15; int nHours = (int) (nOffset / 60); // round towards zero int nMinutes = ABS(nOffset - nHours * 60); if( nOffset < 0 ) { VSIFPrintfL(fp, "-" ); nHours = ABS(nHours); } else VSIFPrintfL(fp, "+" ); VSIFPrintfL(fp, "%02d%02d", nHours, nMinutes ); } } else { VSIFPrintfL(fp, "%s", poFeature->GetFieldAsString(i)); } } if( bClassicGML ) VSIFPrintfL(fp, "</%s>\n", pszName); else VSIFPrintfL(fp, "</property>\n"); CPLFree(pszName); } /* Add OGR_STYLE from feature style string (if asked) */ if( bAddOGRStyleField && poFeatureDefn->GetFieldIndex("OGR_STYLE") < 0 ) { if( bClassicGML ) VSIFPrintfL(fp, " <OGR_STYLE>"); else VSIFPrintfL(fp, " <property name=\"%s\">", "OGR_STYLE"); if( poFeature->GetStyleString() != NULL ) { char* pszValue = OGRGetXML_UTF8_EscapedString( poFeature->GetStyleString() ); VSIFPrintfL(fp, "%s", pszValue); CPLFree(pszValue); } if( bClassicGML ) VSIFPrintfL(fp, "</OGR_STYLE>\n"); else VSIFPrintfL(fp, "</property>\n"); } /* Derive R_G_B field from feature style string */ if( bAddRGBField && poFeatureDefn->GetFieldIndex("R_G_B") < 0 ) { if( bClassicGML ) VSIFPrintfL(fp, " <R_G_B>"); else VSIFPrintfL(fp, " <property name=\"%s\">", "R_G_B"); if( poFeature->GetStyleString() != NULL ) { OGRGeometry* poGeom = poFeature->GetGeometryRef(); OGRwkbGeometryType eGeomType = poGeom ? wkbFlatten(poGeom->getGeometryType()) : wkbUnknown; OGRStyleMgr oMgr; oMgr.InitFromFeature(poFeature); for(int i=0;i<oMgr.GetPartCount();i++) { OGRStyleTool* poTool = oMgr.GetPart(i); if( poTool != NULL ) { const char* pszColor = NULL; if( poTool->GetType() == OGRSTCPen && eGeomType != wkbPolygon && eGeomType != wkbMultiPolygon ) { GBool bIsNull; pszColor = ((OGRStylePen*)poTool)->Color(bIsNull); if( bIsNull ) pszColor = NULL; } else if( poTool->GetType() == OGRSTCBrush ) { GBool bIsNull; pszColor = ((OGRStyleBrush*)poTool)->ForeColor(bIsNull); if( bIsNull ) pszColor = NULL; } int R, G, B, A; if( pszColor != NULL && poTool->GetRGBFromString(pszColor, R, G, B, A) && A != 0 ) { VSIFPrintfL(fp, "%02X%02X%02X", R, G, B); } delete poTool; } } } if( bClassicGML ) VSIFPrintfL(fp, "</R_G_B>\n"); else VSIFPrintfL(fp, "</property>\n"); } VSIFPrintfL(fp, " </feature>\n"); if( bClassicGML ) VSIFPrintfL(fp, " </featureMember>\n"); poFeature->SetFID(nNextFID ++); return OGRERR_NONE; }
OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature ) { int bIsGML3Output = poDS->IsGML3Output(); VSILFILE *fp = poDS->GetOutputFP(); int bWriteSpaceIndentation = poDS->WriteSpaceIndentation(); const char* pszPrefix = poDS->GetAppPrefix(); int bRemoveAppPrefix = poDS->RemoveAppPrefix(); if( !bWriter ) return OGRERR_FAILURE; poFeature->FillUnsetWithDefault(TRUE, NULL); if( !poFeature->Validate( OGR_F_VAL_ALL & ~OGR_F_VAL_GEOM_TYPE & ~OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, TRUE ) ) return OGRERR_FAILURE; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) { if( bRemoveAppPrefix ) poDS->PrintLine( fp, "<featureMember>" ); else poDS->PrintLine( fp, "<%s:featureMember>", pszPrefix ); } else poDS->PrintLine( fp, "<gml:featureMember>" ); if( iNextGMLId == 0 ) { bSameSRS = true; for( int iGeomField = 1; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ ) { OGRGeomFieldDefn *poFieldDefn0 = poFeatureDefn->GetGeomFieldDefn(0); OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField); OGRSpatialReference* poSRS0 = poFieldDefn0->GetSpatialRef(); OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef(); if( poSRS0 != NULL && poSRS == NULL ) bSameSRS = false; else if( poSRS0 == NULL && poSRS != NULL ) bSameSRS = false; else if( poSRS0 != NULL && poSRS != NULL && poSRS0 != poSRS && !poSRS0->IsSame(poSRS) ) { bSameSRS = false; } } } if( poFeature->GetFID() == OGRNullFID ) poFeature->SetFID( iNextGMLId++ ); int nGMLIdIndex = -1; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); VSIFPrintfL(fp, "<"); if( !bRemoveAppPrefix ) VSIFPrintfL(fp, "%s:", pszPrefix); if (bIsGML3Output) { nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id"); if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) ) poDS->PrintLine( fp, "%s gml:id=\"%s\">", poFeatureDefn->GetName(), poFeature->GetFieldAsString(nGMLIdIndex) ); else poDS->PrintLine( fp, "%s gml:id=\"%s." CPL_FRMT_GIB "\">", poFeatureDefn->GetName(), poFeatureDefn->GetName(), poFeature->GetFID() ); } else { nGMLIdIndex = poFeatureDefn->GetFieldIndex("fid"); if (bUseOldFIDFormat) { poDS->PrintLine( fp, "%s fid=\"F" CPL_FRMT_GIB "\">", poFeatureDefn->GetName(), poFeature->GetFID() ); } else if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) ) { poDS->PrintLine( fp, "%s fid=\"%s\">", poFeatureDefn->GetName(), poFeature->GetFieldAsString(nGMLIdIndex) ); } else { poDS->PrintLine( fp, "%s fid=\"%s." CPL_FRMT_GIB "\">", poFeatureDefn->GetName(), poFeatureDefn->GetName(), poFeature->GetFID() ); } } for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ ) { OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField); // Write out Geometry - for now it isn't indented properly. /* GML geometries don't like very much the concept of empty geometry */ OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeomField); if( poGeom != NULL && !poGeom->IsEmpty()) { char *pszGeometry; OGREnvelope3D sGeomBounds; int nCoordDimension = poGeom->getCoordinateDimension(); poGeom->getEnvelope( &sGeomBounds ); if( bSameSRS ) poDS->GrowExtents( &sGeomBounds, nCoordDimension ); if (poGeom->getSpatialReference() == NULL && poFieldDefn->GetSpatialRef() != NULL) poGeom->assignSpatialReference(poFieldDefn->GetSpatialRef()); if (bIsGML3Output && poDS->WriteFeatureBoundedBy()) { bool bCoordSwap; char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap); char szLowerCorner[75], szUpperCorner[75]; if (bCoordSwap) { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, sGeomBounds.MinZ, nCoordDimension); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, sGeomBounds.MaxZ, nCoordDimension); } else { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, sGeomBounds.MinZ, nCoordDimension); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, sGeomBounds.MaxZ, nCoordDimension); } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>", (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",pszSRSName, szLowerCorner, szUpperCorner); CPLFree(pszSRSName); } char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL; if (bIsGML3Output && !poDS->IsLongSRSRequired()) papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO"); const char* pszSRSDimensionLoc = poDS->GetSRSDimensionLoc(); if( pszSRSDimensionLoc != NULL ) papszOptions = CSLSetNameValue(papszOptions, "SRSDIMENSION_LOC", pszSRSDimensionLoc); if (poDS->IsGML32Output()) { if( poFeatureDefn->GetGeomFieldCount() > 1 ) papszOptions = CSLAddString(papszOptions, CPLSPrintf("GMLID=%s.%s." CPL_FRMT_GIB, poFeatureDefn->GetName(), poFieldDefn->GetNameRef(), poFeature->GetFID())); else papszOptions = CSLAddString(papszOptions, CPLSPrintf("GMLID=%s.geom." CPL_FRMT_GIB, poFeatureDefn->GetName(), poFeature->GetFID())); } if( !bIsGML3Output && OGR_GT_IsNonLinear(poGeom->getGeometryType()) ) { OGRGeometry* poGeomTmp = OGRGeometryFactory::forceTo( poGeom->clone(),OGR_GT_GetLinear(poGeom->getGeometryType())); pszGeometry = poGeomTmp->exportToGML(papszOptions); delete poGeomTmp; } else pszGeometry = poGeom->exportToGML(papszOptions); CSLDestroy(papszOptions); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if( bRemoveAppPrefix ) poDS->PrintLine( fp, "<%s>%s</%s>", poFieldDefn->GetNameRef(), pszGeometry, poFieldDefn->GetNameRef() ); else poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>", pszPrefix, poFieldDefn->GetNameRef(), pszGeometry, pszPrefix, poFieldDefn->GetNameRef() ); CPLFree( pszGeometry ); } } // Write all "set" fields. for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ ) { OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField ); if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex ) { OGRFieldType eType = poFieldDefn->GetType(); if (eType == OFTStringList ) { char ** papszIter = poFeature->GetFieldAsStringList( iField ); while( papszIter != NULL && *papszIter != NULL ) { char *pszEscaped = OGRGetXML_UTF8_EscapedString( *papszIter ); GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, pszEscaped); CPLFree( pszEscaped ); papszIter ++; } } else if (eType == OFTIntegerList ) { int nCount = 0; const int* panVals = poFeature->GetFieldAsIntegerList( iField, &nCount ); if( poFieldDefn->GetSubType() == OFSTBoolean ) { for(int i = 0; i < nCount; i++) { /* 0 and 1 are OK, but the canonical representation is false and true */ GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, panVals[i] ? "true" : "false"); } } else { for(int i = 0; i < nCount; i++) { GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, CPLSPrintf("%d", panVals[i])); } } } else if (eType == OFTInteger64List ) { int nCount = 0; const GIntBig* panVals = poFeature->GetFieldAsInteger64List( iField, &nCount ); if( poFieldDefn->GetSubType() == OFSTBoolean ) { for(int i = 0; i < nCount; i++) { /* 0 and 1 are OK, but the canonical representation is false and true */ GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, panVals[i] ? "true" : "false"); } } else { for(int i = 0; i < nCount; i++) { GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, CPLSPrintf(CPL_FRMT_GIB, panVals[i])); } } } else if (eType == OFTRealList ) { int nCount = 0; const double* padfVals = poFeature->GetFieldAsDoubleList( iField, &nCount ); for(int i = 0; i < nCount; i++) { char szBuffer[80]; CPLsnprintf( szBuffer, sizeof(szBuffer), "%.15g", padfVals[i]); GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, szBuffer); } } else if ((eType == OFTInteger || eType == OFTInteger64) && poFieldDefn->GetSubType() == OFSTBoolean ) { /* 0 and 1 are OK, but the canonical representation is false and true */ GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, (poFeature->GetFieldAsInteger(iField)) ? "true" : "false"); } else { const char *pszRaw = poFeature->GetFieldAsString( iField ); char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw ); GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, pszEscaped); CPLFree( pszEscaped ); } } } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if( bRemoveAppPrefix ) poDS->PrintLine( fp, "</%s>", poFeatureDefn->GetName() ); else poDS->PrintLine( fp, "</%s:%s>", pszPrefix, poFeatureDefn->GetName() ); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) { if( bRemoveAppPrefix ) poDS->PrintLine( fp, "</featureMember>" ); else poDS->PrintLine( fp, "</%s:featureMember>", pszPrefix ); } else poDS->PrintLine( fp, "</gml:featureMember>" ); return OGRERR_NONE; }
OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature ) { int bIsGML3Output = poDS->IsGML3Output(); VSILFILE *fp = poDS->GetOutputFP(); int bWriteSpaceIndentation = poDS->WriteSpaceIndentation(); if( !bWriter ) return OGRERR_FAILURE; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) poDS->PrintLine( fp, "<ogr:featureMember>" ); else poDS->PrintLine( fp, "<gml:featureMember>" ); if( poFeature->GetFID() == OGRNullFID ) poFeature->SetFID( iNextGMLId++ ); int nGMLIdIndex = -1; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) { nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id"); if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) ) poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s\">", poFeatureDefn->GetName(), poFeature->GetFieldAsString(nGMLIdIndex) ); else poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s.%ld\">", poFeatureDefn->GetName(), poFeatureDefn->GetName(), poFeature->GetFID() ); } else poDS->PrintLine( fp, "<ogr:%s fid=\"F%ld\">", poFeatureDefn->GetName(), poFeature->GetFID() ); // Write out Geometry - for now it isn't indented properly. /* GML geometries don't like very much the concept of empty geometry */ OGRGeometry* poGeom = poFeature->GetGeometryRef(); if( poGeom != NULL && !poGeom->IsEmpty()) { char *pszGeometry; OGREnvelope sGeomBounds; poGeom->getEnvelope( &sGeomBounds ); poDS->GrowExtents( &sGeomBounds ); if (bIsGML3Output) { int bCoordSwap; if (poGeom->getSpatialReference() == NULL && poSRS != NULL) poGeom->assignSpatialReference(poSRS); char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap); char szLowerCorner[75], szUpperCorner[75]; if (bCoordSwap) { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, 0, 2); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, 0, 2); } else { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, 0, 2); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, 0, 2); } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>", pszSRSName, szLowerCorner, szUpperCorner); CPLFree(pszSRSName); } char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL; if (bIsGML3Output && !poDS->IsLongSRSRequired()) papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO"); pszGeometry = poGeom->exportToGML(papszOptions); CSLDestroy(papszOptions); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<ogr:geometryProperty>%s</ogr:geometryProperty>", pszGeometry ); CPLFree( pszGeometry ); } // Write all "set" fields. for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ ) { OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField ); if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex ) { const char *pszRaw = poFeature->GetFieldAsString( iField ); while( *pszRaw == ' ' ) pszRaw++; char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw ); if (poFieldDefn->GetType() == OFTReal) { /* Use point as decimal separator */ char* pszComma = strchr(pszEscaped, ','); if (pszComma) *pszComma = '.'; } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<ogr:%s>%s</ogr:%s>", poFieldDefn->GetNameRef(), pszEscaped, poFieldDefn->GetNameRef() ); CPLFree( pszEscaped ); } } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "</ogr:%s>", poFeatureDefn->GetName() ); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) poDS->PrintLine( fp, "</ogr:featureMember>" ); else poDS->PrintLine( fp, "</gml:featureMember>" ); return OGRERR_NONE; }
OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature ) { CPLAssert( NULL != poFeature ); CPLAssert( NULL != poDS_ ); if( !bWriter_ ) return OGRERR_FAILURE; if( bClosedForWriting ) { CPLError(CE_Failure, CPLE_NotSupported, "Interleaved feature adding to different layers is not supported"); return OGRERR_FAILURE; } VSILFILE *fp = poDS_->GetOutputFP(); CPLAssert( NULL != fp ); if( poDS_->GetLayerCount() == 1 && nWroteFeatureCount_ == 0 ) { CPLString osRet = WriteSchema(); if( osRet.size() ) VSIFPrintfL( fp, "%s", osRet.c_str() ); bSchemaWritten_ = TRUE; VSIFPrintfL( fp, "<Folder><name>%s</name>\n", pszName_); } VSIFPrintfL( fp, " <Placemark>\n" ); if( poFeature->GetFID() == OGRNullFID ) poFeature->SetFID( iNextKMLId_++ ); // Find and write the name element if (NULL != poDS_->GetNameField()) { for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ ) { OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField ); if( poFeature->IsFieldSet( iField ) && EQUAL(poField->GetNameRef(), poDS_->GetNameField()) ) { const char *pszRaw = poFeature->GetFieldAsString( iField ); while( *pszRaw == ' ' ) pszRaw++; char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw ); VSIFPrintfL( fp, "\t<name>%s</name>\n", pszEscaped); CPLFree( pszEscaped ); } } } if (NULL != poDS_->GetDescriptionField()) { for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ ) { OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField ); if( poFeature->IsFieldSet( iField ) && EQUAL(poField->GetNameRef(), poDS_->GetDescriptionField()) ) { const char *pszRaw = poFeature->GetFieldAsString( iField ); while( *pszRaw == ' ' ) pszRaw++; char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw ); VSIFPrintfL( fp, "\t<description>%s</description>\n", pszEscaped); CPLFree( pszEscaped ); } } } OGRwkbGeometryType eGeomType = wkbNone; if (poFeature->GetGeometryRef() != NULL) eGeomType = wkbFlatten(poFeature->GetGeometryRef()->getGeometryType()); if ( wkbPolygon == eGeomType || wkbMultiPolygon == eGeomType || wkbLineString == eGeomType || wkbMultiLineString == eGeomType ) { OGRStylePen *poPen = NULL; OGRStyleMgr oSM; if( poFeature->GetStyleString() != NULL ) { oSM.InitFromFeature( poFeature ); int i; for(i=0; i<oSM.GetPartCount();i++) { OGRStyleTool *poTool = oSM.GetPart(i); if (poTool && poTool->GetType() == OGRSTCPen ) { poPen = (OGRStylePen*) poTool; break; } delete poTool; } } VSIFPrintfL( fp, "\t<Style>"); if( poPen != NULL ) { GBool bDefault; int bHasWidth = FALSE; /* Require width to be returned in pixel */ poPen->SetUnit(OGRSTUPixel); double fW = poPen->Width(bDefault); if( bDefault ) fW = 1; else bHasWidth = TRUE; const char* pszColor = poPen->Color(bDefault); int nColorLen = static_cast<int>(CPLStrnlen(pszColor, 10)); if( pszColor != NULL && pszColor[0] == '#' && !bDefault && nColorLen >= 7) { char acColor[9] = {0}; /* Order of KML color is aabbggrr, whereas OGR color is #rrggbb[aa] ! */ if(nColorLen == 9) { acColor[0] = pszColor[7]; /* A */ acColor[1] = pszColor[8]; } else { acColor[0] = 'F'; acColor[1] = 'F'; } acColor[2] = pszColor[5]; /* B */ acColor[3] = pszColor[6]; acColor[4] = pszColor[3]; /* G */ acColor[5] = pszColor[4]; acColor[6] = pszColor[1]; /* R */ acColor[7] = pszColor[2]; VSIFPrintfL( fp, "<LineStyle><color>%s</color>", acColor); if (bHasWidth) VSIFPrintfL( fp, "<width>%g</width>", fW); VSIFPrintfL( fp, "</LineStyle>"); } else VSIFPrintfL( fp, "<LineStyle><color>ff0000ff</color></LineStyle>"); } else VSIFPrintfL( fp, "<LineStyle><color>ff0000ff</color></LineStyle>"); delete poPen; //If we're dealing with a polygon, add a line style that will stand out a bit VSIFPrintfL( fp, "<PolyStyle><fill>0</fill></PolyStyle></Style>\n" ); } int bHasFoundOtherField = FALSE; // Write all fields as SchemaData for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ ) { OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField ); if( poFeature->IsFieldSet( iField )) { if (NULL != poDS_->GetNameField() && EQUAL(poField->GetNameRef(), poDS_->GetNameField()) ) continue; if (NULL != poDS_->GetDescriptionField() && EQUAL(poField->GetNameRef(), poDS_->GetDescriptionField()) ) continue; if (!bHasFoundOtherField) { VSIFPrintfL( fp, "\t<ExtendedData><SchemaData schemaUrl=\"#%s\">\n", pszName_ ); bHasFoundOtherField = TRUE; } const char *pszRaw = poFeature->GetFieldAsString( iField ); while( *pszRaw == ' ' ) pszRaw++; char *pszEscaped; if (poFeatureDefn_->GetFieldDefn(iField)->GetType() == OFTReal) { pszEscaped = CPLStrdup( pszRaw ); } else { pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw ); } VSIFPrintfL( fp, "\t\t<SimpleData name=\"%s\">%s</SimpleData>\n", poField->GetNameRef(), pszEscaped); CPLFree( pszEscaped ); } } if (bHasFoundOtherField) { VSIFPrintfL( fp, "\t</SchemaData></ExtendedData>\n" ); } // Write out Geometry - for now it isn't indented properly. if( poFeature->GetGeometryRef() != NULL ) { char* pszGeometry = NULL; OGREnvelope sGeomBounds; OGRGeometry* poWGS84Geom; if (NULL != poCT_) { poWGS84Geom = poFeature->GetGeometryRef()->clone(); poWGS84Geom->transform( poCT_ ); } else { poWGS84Geom = poFeature->GetGeometryRef(); } // TODO - porting // pszGeometry = poFeature->GetGeometryRef()->exportToKML(); pszGeometry = OGR_G_ExportToKML( (OGRGeometryH)poWGS84Geom, poDS_->GetAltitudeMode()); VSIFPrintfL( fp, " %s\n", pszGeometry ); CPLFree( pszGeometry ); poWGS84Geom->getEnvelope( &sGeomBounds ); poDS_->GrowExtents( &sGeomBounds ); if (NULL != poCT_) { delete poWGS84Geom; } } VSIFPrintfL( fp, " </Placemark>\n" ); nWroteFeatureCount_++; return OGRERR_NONE; }