示例#1
0
文件: build_ogr.c 项目: caomw/grass
/*!
   \brief Build pseudo-topology (simple features) for OGR layer

   Build levels:
    - GV_BUILD_NONE
    - GV_BUILD_BASE
    - GV_BUILD_ATTACH_ISLES
    - GV_BUILD_CENTROIDS
    - GV_BUILD_ALL

   \param Map pointer to Map_info structure
   \param build build level

   \return 1 on success
   \return 0 on error
 */
int Vect_build_ogr(struct Map_info *Map, int build)
{
#ifdef HAVE_OGR
    struct Plus_head *plus;
    struct Format_info_ogr *ogr_info;

    plus     = &(Map->plus);
    ogr_info = &(Map->fInfo.ogr);

    G_debug(1, "Vect_build_ogr(): dsn='%s' layer='%s', build=%d",
            ogr_info->dsn, ogr_info->layer_name, build);

    if (build == plus->built)
        return 1;		/* do nothing */

    /* TODO move this init to better place (Vect_open_ ?), because in
       theory build may be reused on level2 */
    if (build >= plus->built && build > GV_BUILD_BASE) {
        G_free((void *) ogr_info->offset.array);
        G_zero(&(ogr_info->offset), sizeof(struct Format_info_offset));
    }

    if (!ogr_info->layer) {
        G_warning(_("Empty OGR layer, nothing to build"));
        return 0;
    }

    if (OGR_L_TestCapability(ogr_info->layer, OLCTransactions))
        OGR_L_CommitTransaction(ogr_info->layer);

    /* test layer capabilities */
    if (!OGR_L_TestCapability(ogr_info->layer, OLCRandomRead)) {
        if (strcmp(OGR_Dr_GetName(OGR_DS_GetDriver(Map->fInfo.ogr.ds)),
                   "PostgreSQL") == 0)
            G_warning(_("Feature table <%s> has no primary key defined"),
                      ogr_info->layer_name);
        G_warning(_("Random read is not supported by OGR for this layer. "
                    "Unable to build topology."));
        return 0;
    }

    if (build > GV_BUILD_NONE)
        G_message(_("Using external data format '%s' (feature type '%s')"),
                  Vect_get_finfo_format_info(Map),
                  Vect_get_finfo_geometry_type(Map));

    return Vect__build_sfa(Map, build);
#else
    G_fatal_error(_("GRASS is not compiled with OGR support"));
    return 0;
#endif
}
示例#2
0
CPLErr CPL_STDCALL
GDALFPolygonize( GDALRasterBandH hSrcBand,
                GDALRasterBandH hMaskBand,
                OGRLayerH hOutLayer, int iPixValField, 
                char **papszOptions,
                GDALProgressFunc pfnProgress, 
                void * pProgressArg )

{
#ifndef OGR_ENABLED
    CPLError(CE_Failure, CPLE_NotSupported, "GDALFPolygonize() unimplemented in a non OGR build");
    return CE_Failure;
#else
    VALIDATE_POINTER1( hSrcBand, "GDALFPolygonize", CE_Failure );
    VALIDATE_POINTER1( hOutLayer, "GDALFPolygonize", CE_Failure );

    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

    int nConnectedness = CSLFetchNameValue( papszOptions, "8CONNECTED" ) ? 8 : 4;

/* -------------------------------------------------------------------- */
/*      Confirm our output layer will support feature creation.         */
/* -------------------------------------------------------------------- */
    if( !OGR_L_TestCapability( hOutLayer, OLCSequentialWrite ) )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Output feature layer does not appear to support creation\n"
                  "of features in GDALFPolygonize()." );
        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Allocate working buffers.                                       */
/* -------------------------------------------------------------------- */
    CPLErr eErr = CE_None;
    int nXSize = GDALGetRasterBandXSize( hSrcBand );
    int nYSize = GDALGetRasterBandYSize( hSrcBand );
    float *pafLastLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
    float *pafThisLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
    GInt32 *panLastLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
    GInt32 *panThisLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
    if (pafLastLineVal == NULL || pafThisLineVal == NULL ||
        panLastLineId == NULL || panThisLineId == NULL ||
        (hMaskBand != NULL && pabyMaskLine == NULL))
    {
        CPLError(CE_Failure, CPLE_OutOfMemory,
                 "Could not allocate enough memory for temporary buffers");
        CPLFree( panThisLineId );
        CPLFree( panLastLineId );
        CPLFree( pafThisLineVal );
        CPLFree( pafLastLineVal );
        CPLFree( pabyMaskLine );
        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Get the geotransform, if there is one, so we can convert the    */
/*      vectors into georeferenced coordinates.                         */
/* -------------------------------------------------------------------- */
    GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
    double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };

    if( hSrcDS )
        GDALGetGeoTransform( hSrcDS, adfGeoTransform );

/* -------------------------------------------------------------------- */
/*      The first pass over the raster is only used to build up the     */
/*      polygon id map so we will know in advance what polygons are     */
/*      what on the second pass.                                        */
/* -------------------------------------------------------------------- */
    int iY;
    GDALRasterFPolygonEnumerator oFirstEnum(nConnectedness);

    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
    {
        eErr = GDALRasterIO( 
            hSrcBand,
            GF_Read, 0, iY, nXSize, 1, 
            pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );
        
        if( eErr == CE_None && hMaskBand != NULL )
            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
                    pafThisLineVal );

        if( iY == 0 )
            oFirstEnum.ProcessLine( 
                NULL, pafThisLineVal, NULL, panThisLineId, nXSize );
        else
            oFirstEnum.ProcessLine(
                pafLastLineVal, pafThisLineVal,
                panLastLineId,  panThisLineId, 
                nXSize );

        // swap lines
        float * pafTmp = pafLastLineVal;
        pafLastLineVal = pafThisLineVal;
        pafThisLineVal = pafTmp;

        GInt32 * panTmp = panThisLineId;
        panThisLineId = panLastLineId;
        panLastLineId = panTmp;

/* -------------------------------------------------------------------- */
/*      Report progress, and support interrupts.                        */
/* -------------------------------------------------------------------- */
        if( eErr == CE_None 
            && !pfnProgress( 0.10 * ((iY+1) / (double) nYSize), 
                             "", pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
            eErr = CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Make a pass through the maps, ensuring every polygon id         */
/*      points to the final id it should use, not an intermediate       */
/*      value.                                                          */
/* -------------------------------------------------------------------- */
    oFirstEnum.CompleteMerges();

/* -------------------------------------------------------------------- */
/*      Initialize ids to -1 to serve as a nodata value for the         */
/*      previous line, and past the beginning and end of the            */
/*      scanlines.                                                      */
/* -------------------------------------------------------------------- */
    int iX;

    panThisLineId[0] = -1;
    panThisLineId[nXSize+1] = -1;

    for( iX = 0; iX < nXSize+2; iX++ )
        panLastLineId[iX] = -1;

/* -------------------------------------------------------------------- */
/*      We will use a new enumerator for the second pass primariliy     */
/*      so we can preserve the first pass map.                          */
/* -------------------------------------------------------------------- */
    GDALRasterFPolygonEnumerator oSecondEnum(nConnectedness);
    RPolygonF **papoPoly = (RPolygonF **)
        CPLCalloc(sizeof(RPolygonF*),oFirstEnum.nNextPolygonId);

/* ==================================================================== */
/*      Second pass during which we will actually collect polygon       */
/*      edges as geometries.                                            */
/* ==================================================================== */
    for( iY = 0; eErr == CE_None && iY < nYSize+1; iY++ )
    {
/* -------------------------------------------------------------------- */
/*      Read the image data.                                            */
/* -------------------------------------------------------------------- */
        if( iY < nYSize )
        {
            eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, 
                                 pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );

            if( eErr == CE_None && hMaskBand != NULL )
                eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
                        pafThisLineVal );
        }

        if( eErr != CE_None )
            continue;

/* -------------------------------------------------------------------- */
/*      Determine what polygon the various pixels belong to (redoing    */
/*      the same thing done in the first pass above).                   */
/* -------------------------------------------------------------------- */
        if( iY == nYSize )
        {
            for( iX = 0; iX < nXSize+2; iX++ )
                panThisLineId[iX] = -1;
        }
        else if( iY == 0 )
            oSecondEnum.ProcessLine( 
                NULL, pafThisLineVal, NULL, panThisLineId+1, nXSize );
        else
            oSecondEnum.ProcessLine(
                pafLastLineVal, pafThisLineVal,
                panLastLineId+1,  panThisLineId+1, 
                nXSize );

/* -------------------------------------------------------------------- */
/*      Add polygon edges to our polygon list for the pixel             */
/*      boundaries within and above this line.                          */
/* -------------------------------------------------------------------- */
        for( iX = 0; iX < nXSize+1; iX++ )
        {
            AddEdges( panThisLineId, panLastLineId, 
                      oFirstEnum.panPolyIdMap, oFirstEnum.pafPolyValue,
                      papoPoly, iX, iY );
        }

/* -------------------------------------------------------------------- */
/*      Periodically we scan out polygons and write out those that      */
/*      haven't been added to on the last line as we can be sure        */
/*      they are complete.                                              */
/* -------------------------------------------------------------------- */
        if( iY % 8 == 7 )
        {
            for( iX = 0; 
                 eErr == CE_None && iX < oSecondEnum.nNextPolygonId; 
                 iX++ )
            {
                if( papoPoly[iX] && papoPoly[iX]->nLastLineUpdated < iY-1 )
                {
                    if( hMaskBand == NULL
                        || !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
                    {
                        eErr = 
                            EmitPolygonToLayer( hOutLayer, iPixValField, 
                                                papoPoly[iX], adfGeoTransform );
                    }
                    delete papoPoly[iX];
                    papoPoly[iX] = NULL;
                }
            }
        }

/* -------------------------------------------------------------------- */
/*      Swap pixel value, and polygon id lines to be ready for the      */
/*      next line.                                                      */
/* -------------------------------------------------------------------- */
        float *pafTmp = pafLastLineVal;
        pafLastLineVal = pafThisLineVal;
        pafThisLineVal = pafTmp;

        GInt32 *panTmp = panThisLineId;
        panThisLineId = panLastLineId;
        panLastLineId = panTmp;

/* -------------------------------------------------------------------- */
/*      Report progress, and support interrupts.                        */
/* -------------------------------------------------------------------- */
        if( eErr == CE_None 
            && !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize), 
                             "", pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
            eErr = CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Make a cleanup pass for all unflushed polygons.                 */
/* -------------------------------------------------------------------- */
    for( iX = 0; eErr == CE_None && iX < oSecondEnum.nNextPolygonId; iX++ )
    {
        if( papoPoly[iX] )
        {
            if( hMaskBand == NULL
                || !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
            {
                eErr = 
                    EmitPolygonToLayer( hOutLayer, iPixValField, 
                                        papoPoly[iX], adfGeoTransform );
            }
            delete papoPoly[iX];
            papoPoly[iX] = NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    CPLFree( panThisLineId );
    CPLFree( panLastLineId );
    CPLFree( pafThisLineVal );
    CPLFree( pafLastLineVal );
    CPLFree( pabyMaskLine );
    CPLFree( papoPoly );

    return eErr;
#endif // OGR_ENABLED
}
示例#3
0
文件: write_ogr.c 项目: caomw/grass
/*!
   \brief Create new OGR layer in given OGR datasource (internal use only)

   V1_open_new_ogr() is required to be called before this function.

   List of currently supported types:
    - GV_POINT     (wkbPoint)
    - GV_LINE      (wkbLineString)
    - GV_BOUNDARY  (wkb_Polygon)
   \param[in,out] Map pointer to Map_info structure
   \param type feature type (GV_POINT, GV_LINE, ...)

   \return 0 success
   \return -1 error 
*/
int create_ogr_layer(struct Map_info *Map, int type)
{
    int ndblinks;
    OGRLayerH            Ogr_layer;
    OGRSpatialReferenceH Ogr_spatial_ref;
    
    struct field_info *Fi;
    struct Key_Value *projinfo, *projunits;
    struct Format_info_ogr *ogr_info;
    
    OGRwkbGeometryType Ogr_geom_type;
    char             **Ogr_layer_options;
    
    ogr_info = &(Map->fInfo.ogr);
    
    if (!ogr_info->driver_name ||
	!ogr_info->layer_name ||
	!ogr_info->ds)
	return -1;
    
    /* get spatial reference */
    projinfo  = G_get_projinfo();
    projunits = G_get_projunits();
    Ogr_spatial_ref = GPJ_grass_to_osr(projinfo, projunits);
    G_free_key_value(projinfo);
    G_free_key_value(projunits);
    
    /* determine geometry type */
    switch(type) {
    case GV_POINT:
	Ogr_geom_type = wkbPoint;
	break;
    case GV_LINE:
	Ogr_geom_type = wkbLineString;
	break;
    case GV_BOUNDARY:
	Ogr_geom_type = wkbPolygon;
	break;
    default:
	G_warning(_("Unsupported geometry type (%d)"), type);
	return -1;
    }
    
    /* check creation options */
    Ogr_layer_options = ogr_info->layer_options;
    if (Vect_is_3d(Map)) {
	if (strcmp(ogr_info->driver_name, "PostgreSQL") == 0) {
	    Ogr_layer_options = CSLSetNameValue(Ogr_layer_options, "DIM", "3");
	}
    }
    else {
	if (strcmp(ogr_info->driver_name, "PostgreSQL") == 0) {
	    Ogr_layer_options = CSLSetNameValue(Ogr_layer_options, "DIM", "2");
	}
    }

    /* create new OGR layer */
    Ogr_layer = OGR_DS_CreateLayer(ogr_info->ds, ogr_info->layer_name,
				   Ogr_spatial_ref, Ogr_geom_type, Ogr_layer_options);
    CSLDestroy(Ogr_layer_options);
    if (!Ogr_layer) {
	G_warning(_("Unable to create OGR layer <%s> in '%s'"),
		  ogr_info->layer_name, ogr_info->dsn);
	return -1;
    }
    ogr_info->layer = Ogr_layer;

    ndblinks = Vect_get_num_dblinks(Map);
    if (ndblinks > 0) {
	/* write also attributes */
	Fi = Vect_get_dblink(Map, 0);
	if (Fi) {
	    if (ndblinks > 1)
		G_warning(_("More layers defined, using driver <%s> and "
			    "database <%s>"), Fi->driver, Fi->database);
	    ogr_info->dbdriver = create_table(ogr_info->layer, Fi);
	    G_free(Fi);
	}
	else
	  G_warning(_("Database connection not defined. "
		      "Unable to write attributes."));
    }
    
    if (OGR_L_TestCapability(ogr_info->layer, OLCTransactions))
	OGR_L_StartTransaction(ogr_info->layer);

    return 0;
}
示例#4
0
/*!
   \brief Open existing OGR layer on non-topological level

   Note: Map->name, Map->mapset, Map->fInfo.ogr.dsn and
   Map->fInfo.ogr.layer_name must be set before.

   \param[in,out] Map pointer to Map_info structure
   \param update TRUE for write mode, otherwise read-only
   
   \return 0 success
   \return -1 error
*/
int V1_open_old_ogr(struct Map_info *Map, int update)
{
#ifdef HAVE_OGR
    int i, layer, nLayers;

    struct Format_info_ogr *ogr_info;
    
    OGRDataSourceH Ogr_ds;
    OGRLayerH Ogr_layer;
    OGRFeatureDefnH Ogr_featuredefn;
    OGRwkbGeometryType Ogr_geom_type;
    
    Ogr_layer = NULL;
    Ogr_geom_type = wkbUnknown;

    ogr_info = &(Map->fInfo.ogr);
    if (!ogr_info->dsn) {
	G_fatal_error(_("OGR datasource not defined"));
	return -1;
    }
    
    if (!ogr_info->layer_name) {
	G_fatal_error(_("OGR layer not defined"));
	return -1;
    }
    
    G_debug(2, "V1_open_old_ogr(): dsn = %s layer = %s", ogr_info->dsn,
	    ogr_info->layer_name);

    OGRRegisterAll();

    /* open data source handle */
    Ogr_ds = OGROpen(ogr_info->dsn, FALSE, NULL);
    if (Ogr_ds == NULL)
	G_fatal_error(_("Unable to open OGR data source '%s'"),
		      ogr_info->dsn);
    ogr_info->ds = Ogr_ds;

    /* get layer number */
    layer = -1;
    nLayers = OGR_DS_GetLayerCount(Ogr_ds);
    G_debug(2, "%d layers found in data source", nLayers);

    for (i = 0; i < nLayers; i++) {
	Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);	
	Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
	if (strcmp(OGR_FD_GetName(Ogr_featuredefn), ogr_info->layer_name) == 0) {
	    Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
	    layer = i;
	    break;
	}
    }
    if (layer == -1) {
	OGR_DS_Destroy(Ogr_ds);
	G_fatal_error(_("OGR layer <%s> not found"),
		      ogr_info->layer_name);
    }
    G_debug(2, "OGR layer %d opened", layer);

    ogr_info->layer = Ogr_layer;
    if (update && OGR_L_TestCapability(ogr_info->layer, OLCTransactions))
	OGR_L_StartTransaction(ogr_info->layer);
    
    switch(Ogr_geom_type) {
    case wkbPoint25D: case wkbLineString25D: case wkbPolygon25D:
    case wkbMultiPoint25D: case wkbMultiLineString25D: case wkbMultiPolygon25D:
    case wkbGeometryCollection25D:
	Map->head.with_z = WITH_Z;
	break;
    default:
	Map->head.with_z = WITHOUT_Z;
	break;
    }
    
    ogr_info->cache.fid = -1;	/* FID >= 0 */
    
    return 0;
#else
    G_fatal_error(_("GRASS is not compiled with OGR support"));
    return -1;
#endif
}