OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature ) { VSILFILE* fp = poDS_->GetOutputFile(); if( NULL == poFeature ) { CPLDebug( "GeoJSON", "Feature is null" ); return OGRERR_INVALID_HANDLE; } json_object* poObj = OGRGeoJSONWriteFeature( poFeature, bWriteBBOX, nCoordPrecision ); CPLAssert( NULL != poObj ); if( nOutCounter_ > 0 ) { /* Separate "Feature" entries in "FeatureCollection" object. */ VSIFPrintfL( fp, ",\n" ); } VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) ); json_object_put( poObj ); ++nOutCounter_; OGRGeometry* poGeometry = poFeature->GetGeometryRef(); if ( bWriteBBOX && !poGeometry->IsEmpty() ) { OGREnvelope3D sEnvelope; poGeometry->getEnvelope(&sEnvelope); if( poGeometry->getCoordinateDimension() == 3 ) bBBOX3D = TRUE; sEnvelopeLayer.Merge(sEnvelope); } return OGRERR_NONE; }
json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision ) { CPLAssert( NULL != poFeature ); json_object* poObj = json_object_new_object(); CPLAssert( NULL != poObj ); json_object_object_add( poObj, "type", json_object_new_string("Feature") ); /* -------------------------------------------------------------------- */ /* Write FID if available */ /* -------------------------------------------------------------------- */ if ( poFeature->GetFID() != OGRNullFID ) { json_object_object_add( poObj, "id", json_object_new_int64(poFeature->GetFID()) ); } /* -------------------------------------------------------------------- */ /* Write feature attributes to GeoJSON "properties" object. */ /* -------------------------------------------------------------------- */ json_object* poObjProps = NULL; poObjProps = OGRGeoJSONWriteAttributes( poFeature ); json_object_object_add( poObj, "properties", poObjProps ); /* -------------------------------------------------------------------- */ /* Write feature geometry to GeoJSON "geometry" object. */ /* Null geometries are allowed, according to the GeoJSON Spec. */ /* -------------------------------------------------------------------- */ json_object* poObjGeom = NULL; OGRGeometry* poGeometry = poFeature->GetGeometryRef(); if ( NULL != poGeometry ) { poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision ); if ( bWriteBBOX && !poGeometry->IsEmpty() ) { OGREnvelope3D sEnvelope; poGeometry->getEnvelope(&sEnvelope); json_object* poObjBBOX = json_object_new_array(); json_object_array_add(poObjBBOX, json_object_new_double_with_precision(sEnvelope.MinX, nCoordPrecision)); json_object_array_add(poObjBBOX, json_object_new_double_with_precision(sEnvelope.MinY, nCoordPrecision)); if (poGeometry->getCoordinateDimension() == 3) json_object_array_add(poObjBBOX, json_object_new_double_with_precision(sEnvelope.MinZ, nCoordPrecision)); json_object_array_add(poObjBBOX, json_object_new_double_with_precision(sEnvelope.MaxX, nCoordPrecision)); json_object_array_add(poObjBBOX, json_object_new_double_with_precision(sEnvelope.MaxY, nCoordPrecision)); if (poGeometry->getCoordinateDimension() == 3) json_object_array_add(poObjBBOX, json_object_new_double_with_precision(sEnvelope.MaxZ, nCoordPrecision)); json_object_object_add( poObj, "bbox", poObjBBOX ); } } json_object_object_add( poObj, "geometry", poObjGeom ); return poObj; }
feature_ptr ogr_featureset::next() { if (count_ == 0) { // Reset the layer reading on the first feature read // this is a hack, but needed due to https://github.com/mapnik/mapnik/issues/2048 // Proper solution is to avoid storing layer state in featureset layer_.ResetReading(); } OGRFeature *poFeature; while ((poFeature = layer_.GetNextFeature()) != nullptr) { // ogr feature ids start at 0, so add one to stay // consistent with other mapnik datasources that start at 1 mapnik::value_integer feature_id = (poFeature->GetFID() + 1); feature_ptr feature(feature_factory::create(ctx_,feature_id)); OGRGeometry* geom = poFeature->GetGeometryRef(); if (geom && ! geom->IsEmpty()) { auto geom_corrected = ogr_converter::convert_geometry(geom); mapnik::geometry::correct(geom_corrected); feature->set_geometry(std::move(geom_corrected)); } else { MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: Feature with null geometry=" << poFeature->GetFID(); OGRFeature::DestroyFeature( poFeature ); continue; } ++count_; int fld_count = layerdef_->GetFieldCount(); for (int i = 0; i < fld_count; i++) { OGRFieldDefn* fld = layerdef_->GetFieldDefn(i); const OGRFieldType type_oid = fld->GetType(); const std::string fld_name = fld->GetNameRef(); switch (type_oid) { case OFTInteger: { feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger(i)); break; } #if GDAL_VERSION_MAJOR >= 2 case OFTInteger64: { feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger64(i)); break; } #endif case OFTReal: { feature->put( fld_name, poFeature->GetFieldAsDouble(i)); break; } case OFTString: case OFTWideString: // deprecated ! { feature->put( fld_name, tr_->transcode(poFeature->GetFieldAsString(i))); break; } case OFTIntegerList: #if GDAL_VERSION_MAJOR >= 2 case OFTInteger64List: #endif case OFTRealList: case OFTStringList: case OFTWideStringList: // deprecated ! { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; break; } case OFTBinary: { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; //feature->put(name,feat->GetFieldAsBinary (i, size)); break; } case OFTDate: case OFTTime: case OFTDateTime: // unhandled ! { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; break; } default: // unknown { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unknown type_oid=" << type_oid; break; } } } OGRFeature::DestroyFeature( poFeature ); return feature; } MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: " << count_ << " features"; return feature_ptr(); }
feature_ptr ogr_featureset::next() { OGRFeature *poFeature; while ((poFeature = layer_.GetNextFeature()) != NULL) { // ogr feature ids start at 0, so add one to stay // consistent with other mapnik datasources that start at 1 const int feature_id = (poFeature->GetFID() + 1); feature_ptr feature(feature_factory::create(ctx_,feature_id)); OGRGeometry* geom = poFeature->GetGeometryRef(); if (geom && ! geom->IsEmpty()) { ogr_converter::convert_geometry(geom, feature); } else { MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: Feature with null geometry=" << poFeature->GetFID(); OGRFeature::DestroyFeature( poFeature ); continue; } ++count_; int fld_count = layerdef_->GetFieldCount(); for (int i = 0; i < fld_count; i++) { OGRFieldDefn* fld = layerdef_->GetFieldDefn(i); const OGRFieldType type_oid = fld->GetType(); const std::string fld_name = fld->GetNameRef(); switch (type_oid) { case OFTInteger: { feature->put( fld_name, poFeature->GetFieldAsInteger(i)); break; } case OFTReal: { feature->put( fld_name, poFeature->GetFieldAsDouble(i)); break; } case OFTString: case OFTWideString: // deprecated ! { UnicodeString ustr = tr_->transcode(poFeature->GetFieldAsString(i)); feature->put( fld_name, ustr); break; } case OFTIntegerList: case OFTRealList: case OFTStringList: case OFTWideStringList: // deprecated ! { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; break; } case OFTBinary: { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; //feature->put(name,feat->GetFieldAsBinary (i, size)); break; } case OFTDate: case OFTTime: case OFTDateTime: // unhandled ! { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; break; } default: // unknown { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unknown type_oid=" << type_oid; break; } } } OGRFeature::DestroyFeature( poFeature ); return feature; } MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: " << count_ << " features"; return feature_ptr(); }
OGRErr OGRBNALayer::CreateFeature( OGRFeature *poFeature ) { int i,j,k,n; OGRGeometry *poGeom = poFeature->GetGeometryRef(); char eol[3]; const char* partialEol = (poDS->GetMultiLine()) ? eol : poDS->GetCoordinateSeparator(); if (poGeom == NULL || poGeom->IsEmpty() ) { CPLError(CE_Failure, CPLE_AppDefined, "OGR BNA driver cannot write features with empty geometries."); return OGRERR_FAILURE; } if (poDS->GetUseCRLF()) { eol[0] = 13; eol[1] = 10; eol[2] = 0; } else { eol[0] = 10; eol[1] = 0; } if ( ! bWriter ) { return OGRERR_FAILURE; } if( poFeature->GetFID() == OGRNullFID ) poFeature->SetFID( nFeatures++ ); VSILFILE* fp = poDS->GetOutputFP(); int nbPairPerLine = poDS->GetNbPairPerLine(); switch( poGeom->getGeometryType() ) { case wkbPoint: case wkbPoint25D: { OGRPoint* point = (OGRPoint*)poGeom; WriteFeatureAttributes(fp, poFeature); VSIFPrintfL( fp, "1"); VSIFPrintfL( fp, "%s", partialEol); WriteCoord(fp, point->getX(), point->getY()); VSIFPrintfL( fp, "%s", eol); break; } case wkbPolygon: case wkbPolygon25D: { OGRPolygon* polygon = (OGRPolygon*)poGeom; OGRLinearRing* ring = polygon->getExteriorRing(); if (ring == NULL) { return OGRERR_FAILURE; } double firstX = ring->getX(0); double firstY = ring->getY(0); int nBNAPoints = ring->getNumPoints(); int is_ellipse = FALSE; /* This code tries to detect an ellipse in a polygon geometry */ /* This will only work presumably on ellipses already read from a BNA file */ /* Mostly a BNA to BNA feature... */ if (poDS->GetEllipsesAsEllipses() && polygon->getNumInteriorRings() == 0 && nBNAPoints == 361) { double oppositeX = ring->getX(180); double oppositeY = ring->getY(180); double quarterX = ring->getX(90); double quarterY = ring->getY(90); double antiquarterX = ring->getX(270); double antiquarterY = ring->getY(270); double center1X = 0.5*(firstX + oppositeX); double center1Y = 0.5*(firstY + oppositeY); double center2X = 0.5*(quarterX + antiquarterX); double center2Y = 0.5*(quarterY + antiquarterY); if (fabs(center1X - center2X) < 1e-5 && fabs(center1Y - center2Y) < 1e-5 && fabs(oppositeY - firstY) < 1e-5 && fabs(quarterX - antiquarterX) < 1e-5) { double major_radius = fabs(firstX - center1X); double minor_radius = fabs(quarterY - center1Y); is_ellipse = TRUE; for(i=0;i<360;i++) { if (!(fabs(center1X + major_radius * cos(i * (M_PI / 180)) - ring->getX(i)) < 1e-5 && fabs(center1Y + minor_radius * sin(i * (M_PI / 180)) - ring->getY(i)) < 1e-5)) { is_ellipse = FALSE; break; } } if ( is_ellipse == TRUE ) { WriteFeatureAttributes(fp, poFeature); VSIFPrintfL( fp, "2"); VSIFPrintfL( fp, "%s", partialEol); WriteCoord(fp, center1X, center1Y); VSIFPrintfL( fp, "%s", partialEol); WriteCoord(fp, major_radius, minor_radius); VSIFPrintfL( fp, "%s", eol); } } } if ( is_ellipse == FALSE) { int nInteriorRings = polygon->getNumInteriorRings(); for(i=0;i<nInteriorRings;i++) { nBNAPoints += polygon->getInteriorRing(i)->getNumPoints() + 1; } if (nBNAPoints <= 3) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" ); return OGRERR_FAILURE; } WriteFeatureAttributes(fp, poFeature); VSIFPrintfL( fp, "%d", nBNAPoints); n = ring->getNumPoints(); int nbPair = 0; for(i=0;i<n;i++) { VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "); WriteCoord(fp, ring->getX(i), ring->getY(i)); nbPair++; } for(i=0;i<nInteriorRings;i++) { ring = polygon->getInteriorRing(i); n = ring->getNumPoints(); for(j=0;j<n;j++) { VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "); WriteCoord(fp, ring->getX(j), ring->getY(j)); nbPair++; } VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "); WriteCoord(fp, firstX, firstY); nbPair++; } VSIFPrintfL( fp, "%s", eol); } break; } case wkbMultiPolygon: case wkbMultiPolygon25D: { OGRMultiPolygon* multipolygon = (OGRMultiPolygon*)poGeom; int N = multipolygon->getNumGeometries(); int nBNAPoints = 0; double firstX = 0, firstY = 0; for(i=0;i<N;i++) { OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i); OGRLinearRing* ring = polygon->getExteriorRing(); if (ring == NULL) continue; if (nBNAPoints) nBNAPoints ++; else { firstX = ring->getX(0); firstY = ring->getY(0); } nBNAPoints += ring->getNumPoints(); int nInteriorRings = polygon->getNumInteriorRings(); for(j=0;j<nInteriorRings;j++) { nBNAPoints += polygon->getInteriorRing(j)->getNumPoints() + 1; } } if (nBNAPoints <= 3) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" ); return OGRERR_FAILURE; } WriteFeatureAttributes(fp, poFeature); VSIFPrintfL( fp, "%d", nBNAPoints); int nbPair = 0; for(i=0;i<N;i++) { OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i); OGRLinearRing* ring = polygon->getExteriorRing(); if (ring == NULL) continue; n = ring->getNumPoints(); int nInteriorRings = polygon->getNumInteriorRings(); for(j=0;j<n;j++) { VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "); WriteCoord(fp, ring->getX(j), ring->getY(j)); nbPair++; } if (i != 0) { VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "); WriteCoord(fp, firstX, firstY); nbPair++; } for(j=0;j<nInteriorRings;j++) { ring = polygon->getInteriorRing(j); n = ring->getNumPoints(); for(k=0;k<n;k++) { VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "); WriteCoord(fp, ring->getX(k), ring->getY(k)); nbPair++; } VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "); WriteCoord(fp, firstX, firstY); nbPair++; } } VSIFPrintfL( fp, "%s", eol); break; } case wkbLineString: case wkbLineString25D: { OGRLineString* line = (OGRLineString*)poGeom; int n = line->getNumPoints(); int i; if (n < 2) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" ); return OGRERR_FAILURE; } WriteFeatureAttributes(fp, poFeature); VSIFPrintfL( fp, "-%d", n); int nbPair = 0; for(i=0;i<n;i++) { VSIFPrintfL( fp, "%s", partialEol); WriteCoord(fp, line->getX(i), line->getY(i)); nbPair++; } VSIFPrintfL( fp, "%s", eol); break; } default: { CPLError( CE_Failure, CPLE_AppDefined, "Unsupported geometry type : %s.", poGeom->getGeometryName() ); return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; } } return OGRERR_NONE; }
OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce ) { OGRFeature *poFeature; OGREnvelope oEnv; GBool bExtentSet = FALSE; psExtent->MinX = 0.0; psExtent->MaxX = 0.0; psExtent->MinY = 0.0; psExtent->MaxY = 0.0; /* -------------------------------------------------------------------- */ /* If this layer has a none geometry type, then we can */ /* reasonably assume there are not extents available. */ /* -------------------------------------------------------------------- */ if( GetLayerDefn()->GetGeomType() == wkbNone ) return OGRERR_FAILURE; /* -------------------------------------------------------------------- */ /* If not forced, we should avoid having to scan all the */ /* features and just return a failure. */ /* -------------------------------------------------------------------- */ if( !bForce ) return OGRERR_FAILURE; /* -------------------------------------------------------------------- */ /* OK, we hate to do this, but go ahead and read through all */ /* the features to collect geometries and build extents. */ /* -------------------------------------------------------------------- */ ResetReading(); while( (poFeature = GetNextFeature()) != NULL ) { OGRGeometry *poGeom = poFeature->GetGeometryRef(); if (poGeom == NULL || poGeom->IsEmpty()) { /* Do nothing */ } else if (!bExtentSet) { poGeom->getEnvelope(psExtent); bExtentSet = TRUE; } else { poGeom->getEnvelope(&oEnv); if (oEnv.MinX < psExtent->MinX) psExtent->MinX = oEnv.MinX; if (oEnv.MinY < psExtent->MinY) psExtent->MinY = oEnv.MinY; if (oEnv.MaxX > psExtent->MaxX) psExtent->MaxX = oEnv.MaxX; if (oEnv.MaxY > psExtent->MaxY) psExtent->MaxY = oEnv.MaxY; } delete poFeature; } ResetReading(); return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE); }
boost::optional<mapnik::datasource_geometry_t> ogr_datasource::get_geometry_type() const { boost::optional<mapnik::datasource_geometry_t> result; if (dataset_ && layer_.is_valid()) { OGRLayer* layer = layer_.layer(); // NOTE: wkbFlatten macro in ogr flattens 2.5d types into base 2d type #if GDAL_VERSION_NUM < 1800 switch (wkbFlatten(layer->GetLayerDefn()->GetGeomType())) #else switch (wkbFlatten(layer->GetGeomType())) #endif { case wkbPoint: case wkbMultiPoint: result.reset(mapnik::datasource_geometry_t::Point); break; case wkbLinearRing: case wkbLineString: case wkbMultiLineString: result.reset(mapnik::datasource_geometry_t::LineString); break; case wkbPolygon: case wkbMultiPolygon: result.reset(mapnik::datasource_geometry_t::Polygon); break; case wkbGeometryCollection: result.reset(mapnik::datasource_geometry_t::Collection); break; case wkbNone: case wkbUnknown: { // fallback to inspecting first actual geometry // TODO - csv and shapefile inspect first 4 features if (dataset_ && layer_.is_valid()) { layer = layer_.layer(); // only new either reset of setNext //layer->ResetReading(); layer->SetNextByIndex(0); OGRFeature *poFeature; while ((poFeature = layer->GetNextFeature()) != nullptr) { OGRGeometry* geom = poFeature->GetGeometryRef(); if (geom && ! geom->IsEmpty()) { switch (wkbFlatten(geom->getGeometryType())) { case wkbPoint: case wkbMultiPoint: result.reset(mapnik::datasource_geometry_t::Point); break; case wkbLinearRing: case wkbLineString: case wkbMultiLineString: result.reset(mapnik::datasource_geometry_t::LineString); break; case wkbPolygon: case wkbMultiPolygon: result.reset(mapnik::datasource_geometry_t::Polygon); break; case wkbGeometryCollection: result.reset(mapnik::datasource_geometry_t::Collection); break; default: break; } } OGRFeature::DestroyFeature( poFeature ); break; } } break; } default: break; } } return result; }
OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature ) { VSILFILE* fp = poDS_->GetOutputFile(); OGRFeature* poFeatureToWrite; if( poCT_ != nullptr || bRFC7946_ ) { poFeatureToWrite = new OGRFeature(poFeatureDefn_); poFeatureToWrite->SetFrom( poFeature ); poFeatureToWrite->SetFID( poFeature->GetFID() ); OGRGeometry* poGeometry = poFeatureToWrite->GetGeometryRef(); if( poGeometry ) { const char* const apszOptions[] = { "WRAPDATELINE=YES", nullptr }; OGRGeometry* poNewGeom = OGRGeometryFactory::transformWithOptions( poGeometry, poCT_, const_cast<char**>(apszOptions), oTransformCache_); if( poNewGeom == nullptr ) { delete poFeatureToWrite; return OGRERR_FAILURE; } OGREnvelope sEnvelope; poNewGeom->getEnvelope(&sEnvelope); if( sEnvelope.MinX < -180.0 || sEnvelope.MaxX > 180.0 || sEnvelope.MinY < -90.0 || sEnvelope.MaxY > 90.0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Geometry extent outside of [-180.0,180.0]x[-90.0,90.0] bounds"); delete poFeatureToWrite; return OGRERR_FAILURE; } poFeatureToWrite->SetGeometryDirectly( poNewGeom ); } } else { poFeatureToWrite = poFeature; } json_object* poObj = OGRGeoJSONWriteFeature( poFeatureToWrite, oWriteOptions_ ); CPLAssert( nullptr != poObj ); if( nOutCounter_ > 0 ) { /* Separate "Feature" entries in "FeatureCollection" object. */ VSIFPrintfL( fp, ",\n" ); } VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) ); json_object_put( poObj ); ++nOutCounter_; OGRGeometry* poGeometry = poFeatureToWrite->GetGeometryRef(); if( bWriteFC_BBOX && poGeometry != nullptr && !poGeometry->IsEmpty() ) { OGREnvelope3D sEnvelope = OGRGeoJSONGetBBox( poGeometry, oWriteOptions_ ); if( poGeometry->getCoordinateDimension() == 3 ) bBBOX3D = true; if( !sEnvelopeLayer.IsInit() ) { sEnvelopeLayer = sEnvelope; } else if( oWriteOptions_.bBBOXRFC7946 ) { const bool bEnvelopeCrossAM = ( sEnvelope.MinX > sEnvelope.MaxX ); const bool bEnvelopeLayerCrossAM = ( sEnvelopeLayer.MinX > sEnvelopeLayer.MaxX ); if( bEnvelopeCrossAM ) { if( bEnvelopeLayerCrossAM ) { sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX, sEnvelope.MinX); sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX, sEnvelope.MaxX); } else { if( sEnvelopeLayer.MinX > 0 ) { sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX, sEnvelope.MinX); sEnvelopeLayer.MaxX = sEnvelope.MaxX; } else if( sEnvelopeLayer.MaxX < 0 ) { sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX, sEnvelope.MaxX); sEnvelopeLayer.MinX = sEnvelope.MinX; } else { sEnvelopeLayer.MinX = -180.0; sEnvelopeLayer.MaxX = 180.0; } } } else if( bEnvelopeLayerCrossAM ) { if( sEnvelope.MinX > 0 ) { sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX, sEnvelope.MinX); } else if( sEnvelope.MaxX < 0 ) { sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX, sEnvelope.MaxX); } else { sEnvelopeLayer.MinX = -180.0; sEnvelopeLayer.MaxX = 180.0; } } else { sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX, sEnvelope.MinX); sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX, sEnvelope.MaxX); } sEnvelopeLayer.MinY = std::min(sEnvelopeLayer.MinY, sEnvelope.MinY); sEnvelopeLayer.MaxY = std::max(sEnvelopeLayer.MaxY, sEnvelope.MaxY); } else { sEnvelopeLayer.Merge(sEnvelope); } } if( poFeatureToWrite != poFeature ) delete poFeatureToWrite; return OGRERR_NONE; }
int main (int argc, const char * argv[]) { time_t startTime = time(NULL); if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { usage(); return(0); } OGRGeometry *geometry; for (int argNum = 1; argNum < argc; ++argNum) { //-- whether to compute the robustness or not if (strcmp(argv[argNum], "--robustness") == 0) { computeRobustness = true; } //-- whether to use the point set topology paradigm or not //-- if not, odd-even paradigm is used by default else if (strcmp(argv[argNum], "--setdiff") == 0) { pointSet = true; } //-- mininum area to keep in output else if (strcmp(argv[argNum], "--minarea") == 0) { minArea = atof(argv[argNum+1]); ++argNum; } //-- ISR snapping tolerance else if (strcmp(argv[argNum], "--isr") == 0) { isrTolerance = atof(argv[argNum+1]); ++argNum; // TODO : scale dataset if tolerance < 1.0 because of CGAL bug } //-- output a shapefile (out.shp) instead of a WKT else if (strcmp(argv[argNum], "--shpOut") == 0) { shpOut = true; } //-- time the results else if (strcmp(argv[argNum], "--time") == 0) { timeResults = true; } //-- reading from WKT passed directly else if (strcmp(argv[argNum], "--wkt") == 0) { unsigned int bufferSize = 100000000; char *inputWKT = (char *)malloc(bufferSize*sizeof(char)); strcpy(inputWKT, argv[argNum+1]); ++argNum; OGRErr err = OGRGeometryFactory::createFromWkt(&inputWKT, NULL, &geometry); if (err != OGRERR_NONE) { switch (err) { case OGRERR_UNSUPPORTED_GEOMETRY_TYPE: std::cerr << "Error: geometry must be Polygon or MultiPolygon" << std::endl; break; case OGRERR_NOT_ENOUGH_DATA: case OGRERR_CORRUPT_DATA: std::cerr << "Error: corrupted input" << std::endl; break; default: std::cerr << "Error: corrupted input" << std::endl; break; } return 1; } if (geometry->IsEmpty() == 1) { std::cerr << "Error: empty geometry" << std::endl; return 1; } if ( (geometry->getGeometryType() != wkbPolygon) && (geometry->getGeometryType() != wkbMultiPolygon) ) { std::cerr << "Error: geometry must be Polygon or MultiPolygon" << std::endl; return 1; } } //-- reading from WKT stored in first line of a text file else if (strcmp(argv[argNum], "-f") == 0) { unsigned int bufferSize = 100000000; char *inputWKT = (char *)malloc(bufferSize*sizeof(char)); if (argNum + 1 <= argc - 1 && argv[argNum+1][0] != '-') { std::ifstream infile(argv[argNum+1], std::ifstream::in); infile.getline(inputWKT, bufferSize); ++argNum; } else { std::cerr << "Error: Missing input file name." << std::endl; return 1; } OGRGeometryFactory::createFromWkt(&inputWKT, NULL, &geometry); if (geometry == NULL) { std::cout << "Error: WKT is not valid" << std::endl; return 1; } } //-- reading from a ogr dataset (most supported: shp, geojson, gml, etc) else if (strcmp(argv[argNum], "--ogr") == 0) { OGRRegisterAll(); OGRDataSource *dataSource = OGRSFDriverRegistrar::Open(argv[argNum+1], false); ++argNum; if (dataSource == NULL) { std::cerr << "Error: Could not open file." << std::endl; return false; } OGRLayer *dataLayer = dataSource->GetLayer(0); //-- get first layer dataLayer->ResetReading(); //-- Reads all features in this layer OGRFeature *feature; //-- get first feature if (dataLayer->GetFeatureCount(true) > 1) std::cout << "Reading only the first feature in the shapefile." << std::endl; feature = dataLayer->GetNextFeature(); if (feature->GetGeometryRef()->getGeometryType() == wkbPolygon) { geometry = static_cast<OGRPolygon *>(feature->GetGeometryRef());feature->GetGeometryRef(); } else { std::cout << "First feature ain't a POLYGON." << std::endl; return(0); } } else { usage(); return(0); } } if (!timeResults) startTime = 0; PolygonRepair prepair; //-- compute robustness if (computeRobustness == true) std::cout << "Robustness of input polygon: " << sqrt(prepair.computeRobustness(geometry)) <<std::endl; OGRMultiPolygon *outPolygons; if (pointSet) { outPolygons = prepair.repairPointSet(geometry, startTime); } else { outPolygons = prepair.repairOddEven(geometry, startTime); } if (minArea > 0) { prepair.removeSmallPolygons(outPolygons, minArea); } //-- output well known text if (shpOut) { prepair.saveToShp(outPolygons, "out.shp"); } else { char *outputWKT; outPolygons->exportToWkt(&outputWKT); std::cout << outputWKT << std::endl; } //-- compute robustness if (computeRobustness == true) std::cout << "Robustness of output polygon: " << sqrt(prepair.computeRobustness()) <<std::endl; //-- time results if (timeResults) { time_t totalTime = time(NULL)-startTime; std::cout << "Done! Process finished in " << totalTime/60 << " minutes " << totalTime%60 << " seconds." << std::endl; } return 0; }
static int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer, int iGeomCol, const LayerDesc& oLayerDesc, const CPLString& osTableName, OGRSQLiteDataSource* poSQLiteDS, sqlite3* hDB, int bSpatialiteDB, const std::set<LayerDesc>& WHEN_SPATIALITE(oSetLayers), const std::set<CPLString>& WHEN_SPATIALITE(oSetSpatialIndex) ) { OGRGeomFieldDefn* poGeomField = poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomCol); CPLString osGeomColRaw; if( iGeomCol == 0 ) osGeomColRaw = OGR2SQLITE_GetNameForGeometryColumn(poLayer); else osGeomColRaw = poGeomField->GetNameRef(); const char* pszGeomColRaw = osGeomColRaw.c_str(); CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw)); const char* pszGeomColEscaped = osGeomColEscaped.c_str(); CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName)); const char* pszLayerNameEscaped = osLayerNameEscaped.c_str(); CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s", oLayerDesc.osLayerName.c_str(), pszGeomColRaw)); CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw)); /* Make sure that the SRS is injected in spatial_ref_sys */ OGRSpatialReference* poSRS = poGeomField->GetSpatialRef(); if( iGeomCol == 0 && poSRS == NULL ) poSRS = poLayer->GetSpatialRef(); int nSRSId = poSQLiteDS->GetUndefinedSRID(); if( poSRS != NULL ) nSRSId = poSQLiteDS->FetchSRSId(poSRS); CPLString osSQL; #ifdef HAVE_SPATIALITE bool bCreateSpatialIndex = false; #endif if( !bSpatialiteDB ) { osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_format, geometry_type, " "coord_dimension, srid) " "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)", pszLayerNameEscaped, pszGeomColEscaped, (int) wkbFlatten(poLayer->GetGeomType()), wkbHasZ( poLayer->GetGeomType() ) ? 3 : 2, nSRSId); } #ifdef HAVE_SPATIALITE else { /* We detect the need for creating a spatial index by 2 means : */ /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */ /* table in the SQL --> old/traditional way of requesting spatial indices */ /* with spatialite. */ std::set<LayerDesc>::const_iterator oIter2 = oSetLayers.begin(); for(; oIter2 != oSetLayers.end(); ++oIter2) { const LayerDesc& oLayerDescIter = *oIter2; if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) ) { bCreateSpatialIndex = true; break; } } /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */ if( !bCreateSpatialIndex ) { std::set<CPLString>::const_iterator oIter3 = oSetSpatialIndex.begin(); for(; oIter3 != oSetSpatialIndex.end(); ++oIter3) { const CPLString& osNameIter = *oIter3; if( EQUAL(osNameIter, oLayerDesc.osLayerName) ) { bCreateSpatialIndex = true; break; } } } if( poSQLiteDS->HasSpatialite4Layout() ) { int nGeomType = poLayer->GetGeomType(); int nCoordDimension = 2; if( wkbHasZ((OGRwkbGeometryType)nGeomType) ) { nGeomType += 1000; nCoordDimension = 3; } osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES (Lower('%s'),Lower('%s'),%d ,%d ,%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, nGeomType, nCoordDimension, nSRSId, static_cast<int>(bCreateSpatialIndex) ); } else { const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType()); if (pszGeometryType[0] == '\0') pszGeometryType = "GEOMETRY"; osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES ('%s','%s','%s','%s',%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, pszGeometryType, wkbHasZ( poLayer->GetGeomType() ) ? "XYZ" : "XY", nSRSId, static_cast<int>(bCreateSpatialIndex) ); } } #endif // HAVE_SPATIALITE char* pszErrMsg = NULL; int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg ); if( pszErrMsg != NULL ) { CPLDebug("SQLITE", "%s -> %s", osSQL.c_str(), pszErrMsg); sqlite3_free(pszErrMsg); } #ifdef HAVE_SPATIALITE /* -------------------------------------------------------------------- */ /* Should we create a spatial index ?. */ /* -------------------------------------------------------------------- */ if( !bSpatialiteDB || !bCreateSpatialIndex ) return rc == SQLITE_OK; CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str()); /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */ #ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING " "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str(), nExtraDS, OGRSQLiteEscape(oLayerDesc.osLayerName).c_str()); rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); if( rc != SQLITE_OK ) { CPLDebug( "SQLITE", "Error occurred during spatial index creation : %s", sqlite3_errmsg(hDB)); } #else // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL ); osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" " "USING rtree(pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str()); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); sqlite3_stmt *hStmt = NULL; if( rc == SQLITE_OK ) { const char* pszInsertInto = CPLSPrintf( "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) " "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str()); rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL); } OGRFeature* poFeature; OGREnvelope sEnvelope; OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer); poLayer->ResetReading(); while( rc == SQLITE_OK && (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry* poGeom = poFeature->GetGeometryRef(); if( poGeom != NULL && !poGeom->IsEmpty() ) { poGeom->getEnvelope(&sEnvelope); sqlite3_bind_int64(hStmt, 1, (sqlite3_int64) poFeature->GetFID() ); sqlite3_bind_double(hStmt, 2, sEnvelope.MinX); sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX); sqlite3_bind_double(hStmt, 4, sEnvelope.MinY); sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY); rc = sqlite3_step(hStmt); if( rc == SQLITE_OK || rc == SQLITE_DONE ) rc = sqlite3_reset(hStmt); } delete poFeature; } poLayer->SetIgnoredFields(NULL); sqlite3_finalize(hStmt); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL ); else { CPLDebug( "SQLITE", "Error occurred during spatial index creation : %s", sqlite3_errmsg(hDB)); rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL ); } #endif // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX #endif // HAVE_SPATIALITE return rc == SQLITE_OK; }
OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature ) { OGRGeometry *poGeom = poFeature->GetGeometryRef(); OGRwkbGeometryType eGType = wkbNone; if( poGeom != nullptr ) { if( !poGeom->IsEmpty() ) { OGREnvelope sEnvelope; poGeom->getEnvelope(&sEnvelope); poDS->UpdateExtent(&sEnvelope); } eGType = wkbFlatten(poGeom->getGeometryType()); } if( eGType == wkbPoint ) { const char *pszBlockName = poFeature->GetFieldAsString("BlockName"); // We don't want to treat as a blocks ref if the block is not defined if( pszBlockName && poDS->oHeaderDS.LookupBlock(pszBlockName) == nullptr ) { if( poDS->poBlocksLayer == nullptr || poDS->poBlocksLayer->FindBlock(pszBlockName) == nullptr ) pszBlockName = nullptr; } if( pszBlockName != nullptr ) return WriteINSERT( poFeature ); else if( poFeature->GetStyleString() != nullptr && STARTS_WITH_CI(poFeature->GetStyleString(), "LABEL") ) return WriteTEXT( poFeature ); else return WritePOINT( poFeature ); } else if( eGType == wkbLineString || eGType == wkbMultiLineString ) return WritePOLYLINE( poFeature ); else if( eGType == wkbPolygon || eGType == wkbTriangle || eGType == wkbMultiPolygon) { if( bWriteHatch ) return WriteHATCH( poFeature ); else return WritePOLYLINE( poFeature ); } // Explode geometry collections into multiple entities. else if( eGType == wkbGeometryCollection ) { OGRGeometryCollection *poGC = poFeature->StealGeometry()->toGeometryCollection(); for( auto&& poMember: poGC ) { poFeature->SetGeometry( poMember ); OGRErr eErr = CreateFeature( poFeature ); if( eErr != OGRERR_NONE ) { delete poGC; return eErr; } } poFeature->SetGeometryDirectly( poGC ); return OGRERR_NONE; } else { CPLError( CE_Failure, CPLE_AppDefined, "No known way to write feature with geometry '%s'.", OGRGeometryTypeToName(eGType) ); return OGRERR_FAILURE; } }
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 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 OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature ) { OGRGeometry *poGeom = poFeature->GetGeometryRef(); OGRwkbGeometryType eGType = wkbNone; if( poGeom != NULL ) { if( !poGeom->IsEmpty() ) { OGREnvelope sEnvelope; poGeom->getEnvelope(&sEnvelope); poDS->UpdateExtent(&sEnvelope); } eGType = wkbFlatten(poGeom->getGeometryType()); } if( eGType == wkbPoint ) { const char *pszBlockName = poFeature->GetFieldAsString("BlockName"); // we don't want to treat as a block ref if we are writing blocks layer if( pszBlockName != NULL && poDS->poBlocksLayer != NULL && poFeature->GetDefnRef() == poDS->poBlocksLayer->GetLayerDefn()) pszBlockName = NULL; // We don't want to treat as a blocks ref if the block is not defined if( pszBlockName && poDS->oHeaderDS.LookupBlock(pszBlockName) == NULL ) { if( poDS->poBlocksLayer == NULL || poDS->poBlocksLayer->FindBlock(pszBlockName) == NULL ) pszBlockName = NULL; } if( pszBlockName != NULL ) return WriteINSERT( poFeature ); else if( poFeature->GetStyleString() != NULL && EQUALN(poFeature->GetStyleString(),"LABEL",5) ) return WriteTEXT( poFeature ); else return WritePOINT( poFeature ); } else if( eGType == wkbLineString || eGType == wkbMultiLineString ) return WritePOLYLINE( poFeature ); else if( eGType == wkbPolygon || eGType == wkbMultiPolygon ) { if( bWriteHatch ) return WriteHATCH( poFeature ); else return WritePOLYLINE( poFeature ); } // Explode geometry collections into multiple entities. else if( eGType == wkbGeometryCollection ) { OGRGeometryCollection *poGC = (OGRGeometryCollection *) poFeature->StealGeometry(); int iGeom; for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ ) { poFeature->SetGeometry( poGC->getGeometryRef(iGeom) ); OGRErr eErr = CreateFeature( poFeature ); if( eErr != OGRERR_NONE ) return eErr; } poFeature->SetGeometryDirectly( poGC ); return OGRERR_NONE; } else { CPLError( CE_Failure, CPLE_AppDefined, "No known way to write feature with geometry '%s'.", OGRGeometryTypeToName(eGType) ); return OGRERR_FAILURE; } }
OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS, const char *pszStatement, OGRGeometry *poSpatialFilter, const char *pszDialect ) { char* pszTmpDBName = (char*) CPLMalloc(256); sprintf(pszTmpDBName, "/vsimem/ogr2sqlite/temp_%p.db", pszTmpDBName); OGRSQLiteDataSource* poSQLiteDS = NULL; int nRet; int bSpatialiteDB = FALSE; CPLString osOldVal; const char* pszOldVal = CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", NULL); if( pszOldVal != NULL ) { osOldVal = pszOldVal; pszOldVal = osOldVal.c_str(); } /* -------------------------------------------------------------------- */ /* Create in-memory sqlite/spatialite DB */ /* -------------------------------------------------------------------- */ #ifdef HAVE_SPATIALITE /* -------------------------------------------------------------------- */ /* Creating an empty spatialite DB (with spatial_ref_sys populated */ /* has a non-neglectable cost. So at the first attempt, let's make */ /* one and cache it for later use. */ /* -------------------------------------------------------------------- */ #if 1 static vsi_l_offset nEmptyDBSize = 0; static GByte* pabyEmptyDB = NULL; { static void* hMutex = NULL; CPLMutexHolder oMutexHolder(&hMutex); static int bTried = FALSE; if( !bTried && CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) ) { bTried = TRUE; char* pszCachedFilename = (char*) CPLMalloc(256); sprintf(pszCachedFilename, "/vsimem/ogr2sqlite/reference_%p.db",pszCachedFilename); char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES"); OGRSQLiteDataSource* poCachedDS = new OGRSQLiteDataSource(); nRet = poCachedDS->Create( pszCachedFilename, papszOptions ); CSLDestroy(papszOptions); papszOptions = NULL; delete poCachedDS; if( nRet ) /* Note: the reference file keeps the ownership of the data, so that */ /* it gets released with VSICleanupFileManager() */ pabyEmptyDB = VSIGetMemFileBuffer( pszCachedFilename, &nEmptyDBSize, FALSE ); CPLFree( pszCachedFilename ); } } /* The following configuration option is usefull mostly for debugging/testing */ if( pabyEmptyDB != NULL && CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) ) { GByte* pabyEmptyDBClone = (GByte*)VSIMalloc(nEmptyDBSize); if( pabyEmptyDBClone == NULL ) { CPLFree(pszTmpDBName); return NULL; } memcpy(pabyEmptyDBClone, pabyEmptyDB, nEmptyDBSize); VSIFCloseL(VSIFileFromMemBuffer( pszTmpDBName, pabyEmptyDBClone, nEmptyDBSize, TRUE )); poSQLiteDS = new OGRSQLiteDataSource(); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO"); nRet = poSQLiteDS->Open( pszTmpDBName, TRUE ); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal); if( !nRet ) { /* should not happen really ! */ delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } bSpatialiteDB = TRUE; } #else /* No caching version */ poSQLiteDS = new OGRSQLiteDataSource(); char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES"); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO"); nRet = poSQLiteDS->Create( pszTmpDBName, papszOptions ); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal); CSLDestroy(papszOptions); papszOptions = NULL; if( nRet ) { bSpatialiteDB = TRUE; } #endif else { delete poSQLiteDS; poSQLiteDS = NULL; #else // HAVE_SPATIALITE if( TRUE ) { #endif // HAVE_SPATIALITE poSQLiteDS = new OGRSQLiteDataSource(); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO"); nRet = poSQLiteDS->Create( pszTmpDBName, NULL ); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal); if( !nRet ) { delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } } /* -------------------------------------------------------------------- */ /* Attach the Virtual Table OGR2SQLITE module to it. */ /* -------------------------------------------------------------------- */ OGR2SQLITEModule* poModule = OGR2SQLITE_Setup(poDS, poSQLiteDS); sqlite3* hDB = poSQLiteDS->GetDB(); /* -------------------------------------------------------------------- */ /* Analysze the statement to determine which tables will be used. */ /* -------------------------------------------------------------------- */ std::set<LayerDesc> oSetLayers; std::set<CPLString> oSetSpatialIndex; CPLString osModifiedSQL; OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex, osModifiedSQL); std::set<LayerDesc>::iterator oIter = oSetLayers.begin(); if( strcmp(pszStatement, osModifiedSQL.c_str()) != 0 ) CPLDebug("OGR", "Modified SQL: %s", osModifiedSQL.c_str()); pszStatement = osModifiedSQL.c_str(); /* do not use it anymore */ int bFoundOGRStyle = ( osModifiedSQL.ifind("OGR_STYLE") != std::string::npos ); /* -------------------------------------------------------------------- */ /* For each of those tables, create a Virtual Table. */ /* -------------------------------------------------------------------- */ for(; oIter != oSetLayers.end(); ++oIter) { const LayerDesc& oLayerDesc = *oIter; /*CPLDebug("OGR", "Layer desc : %s, %s, %s, %s", oLayerDesc.osOriginalStr.c_str(), oLayerDesc.osSubstitutedName.c_str(), oLayerDesc.osDSName.c_str(), oLayerDesc.osLayerName.c_str());*/ CPLString osSQL; OGRLayer* poLayer = NULL; CPLString osTableName; int nExtraDS; if( oLayerDesc.osDSName.size() == 0 ) { poLayer = poDS->GetLayerByName(oLayerDesc.osLayerName); /* Might be a false positive (unlikely) */ if( poLayer == NULL ) continue; osTableName = oLayerDesc.osLayerName; nExtraDS = -1; osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)", OGRSQLiteEscapeName(osTableName).c_str(), nExtraDS, OGRSQLiteEscape(osTableName).c_str(), bFoundOGRStyle); } else { OGRDataSource* poOtherDS = (OGRDataSource* ) OGROpen(oLayerDesc.osDSName, FALSE, NULL); if( poOtherDS == NULL ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot open datasource '%s'", oLayerDesc.osDSName.c_str() ); delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } poLayer = poOtherDS->GetLayerByName(oLayerDesc.osLayerName); if( poLayer == NULL ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find layer '%s' in '%s'", oLayerDesc.osLayerName.c_str(), oLayerDesc.osDSName.c_str() ); delete poOtherDS; delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } osTableName = oLayerDesc.osSubstitutedName; nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS); osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)", OGRSQLiteEscapeName(osTableName).c_str(), nExtraDS, OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(), bFoundOGRStyle); } char* pszErrMsg = NULL; int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg ); if( rc != SQLITE_OK ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot create virtual table for layer '%s' : %s", osTableName.c_str(), pszErrMsg); sqlite3_free(pszErrMsg); continue; } if( poLayer->GetGeomType() == wkbNone ) continue; CPLString osGeomColRaw(OGR2SQLITE_GetNameForGeometryColumn(poLayer)); const char* pszGeomColRaw = osGeomColRaw.c_str(); CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw)); const char* pszGeomColEscaped = osGeomColEscaped.c_str(); CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName)); const char* pszLayerNameEscaped = osLayerNameEscaped.c_str(); CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s", oLayerDesc.osLayerName.c_str(), pszGeomColRaw)); CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw)); /* Make sure that the SRS is injected in spatial_ref_sys */ OGRSpatialReference* poSRS = poLayer->GetSpatialRef(); int nSRSId = poSQLiteDS->GetUndefinedSRID(); if( poSRS != NULL ) nSRSId = poSQLiteDS->FetchSRSId(poSRS); int bCreateSpatialIndex = FALSE; if( !bSpatialiteDB ) { osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_format, geometry_type, " "coord_dimension, srid) " "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)", pszLayerNameEscaped, pszGeomColEscaped, (int) wkbFlatten(poLayer->GetGeomType()), ( poLayer->GetGeomType() & wkb25DBit ) ? 3 : 2, nSRSId); } #ifdef HAVE_SPATIALITE else { /* We detect the need for creating a spatial index by 2 means : */ /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */ /* table in the SQL --> old/traditionnal way of requesting spatial indices */ /* with spatialite. */ std::set<LayerDesc>::iterator oIter2 = oSetLayers.begin(); for(; oIter2 != oSetLayers.end(); ++oIter2) { const LayerDesc& oLayerDescIter = *oIter2; if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) ) { bCreateSpatialIndex = TRUE; break; } } /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */ if( !bCreateSpatialIndex ) { std::set<CPLString>::iterator oIter3 = oSetSpatialIndex.begin(); for(; oIter3 != oSetSpatialIndex.end(); ++oIter3) { const CPLString& osNameIter = *oIter3; if( EQUAL(osNameIter, oLayerDesc.osLayerName) ) { bCreateSpatialIndex = TRUE; break; } } } if( poSQLiteDS->HasSpatialite4Layout() ) { int nGeomType = poLayer->GetGeomType(); int nCoordDimension = 2; if( nGeomType & wkb25DBit ) { nGeomType += 1000; nCoordDimension = 3; } osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES ('%s',Lower('%s'),%d ,%d ,%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, nGeomType, nCoordDimension, nSRSId, bCreateSpatialIndex ); } else { const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType()); if (pszGeometryType[0] == '\0') pszGeometryType = "GEOMETRY"; osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES ('%s','%s','%s','%s',%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, pszGeometryType, ( poLayer->GetGeomType() & wkb25DBit ) ? "XYZ" : "XY", nSRSId, bCreateSpatialIndex ); } } #endif // HAVE_SPATIALITE sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); #ifdef HAVE_SPATIALITE /* -------------------------------------------------------------------- */ /* Should we create a spatial index ?. */ /* -------------------------------------------------------------------- */ if( !bSpatialiteDB || !bCreateSpatialIndex ) continue; CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str()); /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */ #ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING " "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str(), nExtraDS, OGRSQLiteEscape(oLayerDesc.osLayerName).c_str()); rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); if( rc != SQLITE_OK ) { CPLDebug("SQLITE", "Error occured during spatial index creation : %s", sqlite3_errmsg(hDB)); } #else // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL ); osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" " "USING rtree(pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str()); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); sqlite3_stmt *hStmt = NULL; if( rc == SQLITE_OK ) { const char* pszInsertInto = CPLSPrintf( "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) " "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str()); rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL); } OGRFeature* poFeature; OGREnvelope sEnvelope; OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer); poLayer->ResetReading(); while( rc == SQLITE_OK && (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry* poGeom = poFeature->GetGeometryRef(); if( poGeom != NULL && !poGeom->IsEmpty() ) { poGeom->getEnvelope(&sEnvelope); sqlite3_bind_int64(hStmt, 1, (sqlite3_int64) poFeature->GetFID() ); sqlite3_bind_double(hStmt, 2, sEnvelope.MinX); sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX); sqlite3_bind_double(hStmt, 4, sEnvelope.MinY); sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY); rc = sqlite3_step(hStmt); if( rc == SQLITE_OK || rc == SQLITE_DONE ) rc = sqlite3_reset(hStmt); } delete poFeature; } poLayer->SetIgnoredFields(NULL); sqlite3_finalize(hStmt); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL ); else { CPLDebug("SQLITE", "Error occured during spatial index creation : %s", sqlite3_errmsg(hDB)); rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL ); } #endif // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX #endif // HAVE_SPATIALITE } /* -------------------------------------------------------------------- */ /* Reload, so that virtual tables are recognized */ /* -------------------------------------------------------------------- */ poSQLiteDS->ReloadLayers(); /* -------------------------------------------------------------------- */ /* Prepare the statement. */ /* -------------------------------------------------------------------- */ /* This will speed-up layer creation */ /* ORDER BY are costly to evaluate and are not necessary to establish */ /* the layer definition. */ int bUseStatementForGetNextFeature = TRUE; int bEmptyLayer = FALSE; sqlite3_stmt *hSQLStmt = NULL; int rc = sqlite3_prepare( hDB, pszStatement, strlen(pszStatement), &hSQLStmt, NULL ); if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "In ExecuteSQL(): sqlite3_prepare(%s):\n %s", pszStatement, sqlite3_errmsg(hDB) ); if( hSQLStmt != NULL ) { sqlite3_finalize( hSQLStmt ); } delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } /* -------------------------------------------------------------------- */ /* Do we get a resultset? */ /* -------------------------------------------------------------------- */ rc = sqlite3_step( hSQLStmt ); if( rc != SQLITE_ROW ) { if ( rc != SQLITE_DONE ) { CPLError( CE_Failure, CPLE_AppDefined, "In ExecuteSQL(): sqlite3_step(%s):\n %s", pszStatement, sqlite3_errmsg(hDB) ); sqlite3_finalize( hSQLStmt ); delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } if( !EQUALN(pszStatement, "SELECT ", 7) ) { sqlite3_finalize( hSQLStmt ); delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } bUseStatementForGetNextFeature = FALSE; bEmptyLayer = TRUE; } /* -------------------------------------------------------------------- */ /* Create layer. */ /* -------------------------------------------------------------------- */ OGRSQLiteSelectLayer *poLayer = NULL; poLayer = new OGRSQLiteExecuteSQLLayer( pszTmpDBName, poSQLiteDS, pszStatement, hSQLStmt, bUseStatementForGetNextFeature, bEmptyLayer ); if( poSpatialFilter != NULL ) poLayer->SetSpatialFilter( poSpatialFilter ); return poLayer; } /************************************************************************/ /* OGRSQLiteGetReferencedLayers() */ /************************************************************************/ std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement) { /* -------------------------------------------------------------------- */ /* Analysze the statement to determine which tables will be used. */ /* -------------------------------------------------------------------- */ std::set<LayerDesc> oSetLayers; std::set<CPLString> oSetSpatialIndex; CPLString osModifiedSQL; OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex, osModifiedSQL); return oSetLayers; }
void OGRJMLLayer::endElementCbk(const char *pszName) { if (bStopParsing) return; nWithoutEventCounter = 0; currentDepth--; if( nAttributeElementDepth == currentDepth ) { if( nElementValueLen ) poFeature->SetField(iAttr, pszElementValue); else if( iAttr >= 0 ) poFeature->SetFieldNull(iAttr); nAttributeElementDepth = 0; StopAccumulate(); } else if( nGeometryElementDepth > 0 && currentDepth > nGeometryElementDepth ) { AddStringToElementValue("</", 2); AddStringToElementValue(pszName, static_cast<int>(strlen(pszName))); AddStringToElementValue(">", 1); } else if( nGeometryElementDepth == currentDepth ) { if( nElementValueLen ) { OGRGeometry* poGeom = reinterpret_cast<OGRGeometry *>( OGR_G_CreateFromGML(pszElementValue) ); if( poGeom != nullptr && poGeom->getGeometryType() == wkbGeometryCollection && poGeom->IsEmpty() ) { delete poGeom; } else poFeature->SetGeometryDirectly(poGeom); } nGeometryElementDepth = 0; StopAccumulate(); } else if( nFeatureElementDepth == currentDepth ) { /* Builds a style string from R_G_B if we don't already have a */ /* style string */ OGRGeometry* poGeom = poFeature->GetGeometryRef(); unsigned int R = 0; unsigned int G = 0; unsigned int B = 0; if( iRGBField >= 0 && poFeature->IsFieldSetAndNotNull(iRGBField) && poFeature->GetStyleString() == nullptr && poGeom != nullptr && sscanf(poFeature->GetFieldAsString(iRGBField), "%02X%02X%02X", &R, &G, &B) == 3 ) { const OGRwkbGeometryType eGeomType = wkbFlatten(poGeom->getGeometryType()); if( eGeomType == wkbPoint || eGeomType == wkbMultiPoint || eGeomType == wkbLineString || eGeomType == wkbMultiLineString ) { poFeature->SetStyleString( CPLSPrintf("PEN(c:#%02X%02X%02X)", R, G, B)); } else if( eGeomType == wkbPolygon || eGeomType == wkbMultiPolygon ) { poFeature->SetStyleString( CPLSPrintf("BRUSH(fc:#%02X%02X%02X)", R, G, B)); } } poFeature->SetFID(nNextFID++); if( (m_poFilterGeom == nullptr || FilterGeometry( poGeom ) ) && (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate( poFeature )) ) { ppoFeatureTab = static_cast<OGRFeature**>( CPLRealloc(ppoFeatureTab, sizeof(OGRFeature*) * (nFeatureTabLength + 1)) ); ppoFeatureTab[nFeatureTabLength] = poFeature; nFeatureTabLength++; } else { delete poFeature; } poFeature = nullptr; iAttr = -1; nFeatureElementDepth = 0; } else if( nFeatureCollectionDepth == currentDepth ) { nFeatureCollectionDepth = 0; } }