Changeset 5516

Show
Ignore:
Timestamp:
04/09/10 06:34:35 (2 years ago)
Author:
jorgearevalo
Message:

SQL function ST_DumpAsPolygons created, under conditional compilation. It still
has errors. So, it's NOT SAFE to use it. Default version returning NULL if don't
specify --enable-development option in configure script created. Related ticket: #297

Location:
spike/wktraster
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • spike/wktraster/rt_core/rt_api.c

    r5482 r5516  
    13131313    int srid; 
    13141314    double val; 
    1315     char * wktPol; 
     1315    char * wktGeom; 
    13161316}; 
    13171317 
     
    13191319#ifdef ENABLE_DEVELOPMENT 
    13201320rt_wktgeomval 
    1321 rt_raster_as_wktpolygon(rt_context ctx, rt_raster raster, int nband) 
     1321rt_raster_dump_as_wktpolygons(rt_context ctx, rt_raster raster, int nband) 
    13221322{ 
    13231323    char szDataPointer[50]; 
     
    14051405    memdataset = GDALCreate(GDALGetDriverByName("MEM"), 
    14061406                                   "",rt_band_get_width(ctx, band),  
    1407                                    rt_band_get_height(ctx, band), 0, GDT_Byte, 
    1408                                    NULL); 
     1407                                   rt_band_get_height(ctx, band), 0,  
     1408                                   GDT_Byte, NULL); 
    14091409 
    14101410    if (NULL == memdataset) 
     
    15961596 
    15971597        /** 
    1598          * The field was stored as int, but we can use this function because 
    1599          * uses "atof" to transform the string representation of the number 
    1600          * into a double. We shouldn't have problems 
     1598         * The field was stored as int, but we can use this function  
     1599         * because uses "atof" to transform the string representation of  
     1600         * the number into a double. We shouldn't have problems 
    16011601         **/ 
    16021602        dValueToCompare = OGR_F_GetFieldAsDouble(hFeature, iPixVal); 
     
    16071607         * the associated polygon is discarded 
    16081608         **/ 
    1609        dEpsilon = fabs(dValueToCompare - dBandNoData); 
    1610        if (dEpsilon > FLT_EPSILON) 
     1609        dEpsilon = fabs(dValueToCompare - dBandNoData); 
     1610        if (dEpsilon > FLT_EPSILON) 
    16111611            nValidPols--; 
    16121612    } 
     
    16301630        dEpsilon = fabs(dValueToCompare - dBandNoData); 
    16311631 
    1632         // Valid polygon 
     1632        /* Valid polygon */ 
    16331633        if (dEpsilon > FLT_EPSILON) 
    16341634        { 
     
    16361636            OGR_G_ExportToWkt(hGeom, &pszSrcText); 
    16371637             
    1638             // Fill rt_wktgeomval structure 
     1638            /* Fill rt_wktgeomval structure */ 
    16391639            pols[nCont].val = OGR_F_GetFieldAsInteger(hFeature, iPixVal);  
    16401640            pols[nCont].srid = rt_raster_get_srid(ctx, raster); 
    1641             pols[nCont].wktPol = (char *)ctx->alloc(strlen(pszSrcText)  
     1641            pols[nCont].wktGeom = (char *)ctx->alloc(strlen(pszSrcText)  
    16421642                    * sizeof(char)); 
    1643             strcpy(pols[nCont].wktPol, pszSrcText);             
    1644  
    1645 #ifdef POSTGIS_RASTER_API_DEBUG 
    1646             ctx->info("Feature %d, WKT Polygon: %s", j, pols[nCont].wktPol); 
     1643            strcpy(pols[nCont].wktGeom, pszSrcText);             
     1644 
     1645#ifdef POSTGIS_RASTER_API_DEBUG 
     1646            ctx->info("Feature %d, WKT Polygon: %s", j, pols[nCont].wktGeom); 
    16471647            ctx->info("Feature %d, value: %d", j, (int)(pols[nCont].val)); 
    16481648            ctx->info("Feature %d, srid: %d", j, pols[nCont].srid); 
     
    16661666 
    16671667rt_wktgeomval 
    1668 rt_raster_as_wktpolygon(rt_context ctx, rt_raster raster, int nband) 
     1668rt_raster_dump_as_wktpolygons(rt_context ctx, rt_raster raster, int nband) 
    16691669{ 
    16701670    /** 
     
    16761676} 
    16771677 
    1678 #endif // ENABLE_DEVELOPMENT 
     1678#endif /* ENABLE_DEVELOPMENT */ 
    16791679 
    16801680 
  • spike/wktraster/rt_core/rt_api.h

    r5425 r5516  
    542542 */ 
    543543rt_wktgeomval 
    544 rt_raster_as_wktpolygon(rt_context ctx, rt_raster raster, int nband); 
     544rt_raster_dump_as_wktpolygons(rt_context ctx, rt_raster raster, int nband); 
    545545 
    546546/** 
  • spike/wktraster/rt_pg/rt_pg.c

    r5500 r5516  
    8888Datum RASTER_to_LWGEOM(PG_FUNCTION_ARGS); 
    8989Datum RASTER_to_BOX2DFLOAT4(PG_FUNCTION_ARGS); 
     90Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS); 
    9091 
    9192/* Get all the properties of a raster */ 
     
    517518    PG_RETURN_POINTER(bbox); 
    518519} 
     520 
     521 
     522 
     523 
     524/** 
     525 * Needed for sizeof 
     526 */ 
     527struct rt_wktgeomval_t { 
     528    int srid; 
     529    double val; 
     530    char * wktGeom; 
     531}; 
     532 
     533 
     534/** 
     535 * Need this to store the set of structs and a index to know 
     536 * which struct should I get in each call 
     537 */ 
     538 
     539struct rt_wktgeomval_ind_t { 
     540    rt_wktgeomval geomval; 
     541    int index; 
     542}; 
     543 
     544typedef struct rt_wktgeomval_ind_t* rt_wktgeomval_ind; 
     545 
     546  
     547#ifdef ENABLE_DEVELOPMENT 
     548 
     549 
     550/** 
     551 * Returns a set of "geomval" value, one for each group of pixel sharing the same value for the provided band. 
     552 */ 
     553PG_FUNCTION_INFO_V1(RASTER_asWKTPolygon); 
     554Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS) 
     555{ 
     556    rt_pgraster *pgraster; 
     557    rt_raster raster; 
     558    rt_context ctx = get_rt_context(fcinfo); 
     559    FuncCallContext *funcctx; 
     560    int call_cntr; 
     561    int max_calls; 
     562    TupleDesc tupdesc; 
     563    AttInMetadata *attinmeta; 
     564    int nband; 
     565    rt_wktgeomval geomval; 
     566    rt_wktgeomval_ind geomval_ind; 
     567 
     568 
     569    /** 
     570     * Check input parameters 
     571     */ 
     572    if ( PG_NARGS() < 1 || PG_NARGS() > 2 ) 
     573    { 
     574        ereport(errcode(ERRCODE_TOO_MANY_ARGUMENTS),  
     575                (errmsg("RASTER_dumpAsWKTPolygons requires 1 or 2 args"))); 
     576        PG_RETURN_NULL(); 
     577    } 
     578 
     579    /** 
     580     * Stuff donde only in the first call of the function 
     581     */ 
     582    if (SRF_IS_FIRSTCALL()) 
     583    { 
     584        MemoryContext oldcontext; 
     585 
     586        /* Create a function context for cross-call persistence */ 
     587        funcctx = SRF_FIRSTCALL_INIT(); 
     588 
     589        /* switch to memory context appropriate for multiple function  
     590           calls */ 
     591        oldcontext =  
     592            MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); 
     593        
     594        /* Get raster context. We change to a valid memory context 
     595         * (fcinfo->flinfo->fn_mcxt) to create a new rt_context. So, all 
     596         * the memory operations performed in rt_api core function called 
     597         * will be based on palloc. See palloc advantages at PostgreSQL 
     598         * source, in src/backend/utils/mmgr/README 
     599         */ 
     600        ctx = get_rt_context(fcinfo); 
     601 
     602        /* Get input arguments */ 
     603        pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
     604        raster = rt_raster_deserialize(ctx, pgraster); 
     605        if ( ! raster )  
     606        { 
     607            ereport(errcode(ERRCODE_OUT_OF_MEMORY),  
     608                    (errmsg("Could not deserialize raster"))); 
     609            PG_RETURN_NULL(); 
     610        } 
     611 
     612        if (PG_NARGS() == 2) 
     613            nband = PG_GETARG_UINT32(1); 
     614        else 
     615            nband = 1; /* By default, first band */ 
     616 
     617        /* Polygonize raster */ 
     618        geomval = rt_raster_dump_as_wktpolygons(ctx, raster, nband); 
     619        /** 
     620         * Not needed to check geomval. It was allocated by the new 
     621         * rt_context, that uses palloc. It never returns NULL 
     622         */ 
     623        
     624        /** 
     625         * Total number of tuples to be return 
     626         * xxx jorgearevalo: Check if this works... 
     627         */ 
     628        funcctx->max_calls =  
     629            sizeof(geomval) / sizeof(rt_wktgeomval); 
     630 
     631        /**  
     632         * Store needed information 
     633         */ 
     634        geomval_ind = (rt_wktgeomval_ind *)palloc(1*sizeof(rt_wktgeomval)); 
     635        if ( ! geomval_ind) 
     636        { 
     637            ereport(errcode(ERRCODE_OUT_OF_MEMORY),  
     638                    (errmsg("Out of memory"))); 
     639            PG_RETURN_NULL(); 
     640        } 
     641        geomval_ind->geomval = geomval; 
     642        geomval_ind->index = 0; 
     643        funcctx->user_fctx = geomval_ind; 
     644 
     645        /* Build a tuple descriptor for our result type */ 
     646        if (get_call_result_type(fcinfo, NULL, &tupdesc) !=  
     647                TYPEFUNC_COMPOSITE) 
     648        { 
     649            ereport(ERROR, 
     650                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 
     651                     errmsg("Function returning record called in context " 
     652                            "that cannot accept type record"))); 
     653        } 
     654 
     655 
     656        /* Generate attribute metadata needed later to produce tuples 
     657           for raw C strings */ 
     658        attinmeta = TupleDescGetAttInMetadata(tupdesc); 
     659        funcctx->attinmeta = attinmeta; 
     660 
     661        MemoryContextSwitchTo(oldcontext); 
     662    } 
     663 
     664    /* Stuff done on every call of the function */ 
     665    funcctx = SRF_PERCALL_SETUP(); 
     666    call_cntr = funcctx->call_cntr; 
     667    max_calls = funcctx->max_calls; 
     668    attinmeta = funcctx->attinmeta; 
     669    geomval_ind = funcctx->user_fctx; 
     670 
     671    /* If there is more left to send... */ 
     672    if (call_cntr < max_calls) 
     673    { 
     674        char ** values; 
     675        HeapTuple tuple; 
     676        Datum result; 
     677 
     678        /** 
     679         * Prepare a values array for building the returned tuple. 
     680         * This should be an array of C strings which will be processed 
     681         * later by the type input functions 
     682         */ 
     683        values = (char **)palloc(3 * sizeof(char *)); 
     684        values[0] = (char *)palloc(sizeof(int) * sizeof(char)); 
     685        values[1] = (char *)palloc( 
     686                strlen(geomval_ind->geomval[geomval_ind->index].wktGeom) * sizeof(char)); 
     687        values[2] = (char *)palloc(sizeof(double) * sizeof(char)); 
     688 
     689        snprintf(values[0], sizeof(int), "%d", 
     690                geomval_ind->geomval[geomval_ind->index].srid); 
     691        snprintf(values[1],  
     692                strlen(geomval_ind->geomval[geomval_ind->index].wktGeom), 
     693                "%s", geomval_ind->geomval[geomval_ind->index].wktGeom); 
     694        snprintf(values[2], sizeof(double), "%f", 
     695                geomval_ind->geomval[geomval_ind->index].val); 
     696         
     697        /* Build a tuple */ 
     698        tuple = BuildTupleFromCStrings(attinmeta, values); 
     699 
     700        /* Make the tuple into a datum */ 
     701        result = HeapTupleGetDatum(tuple); 
     702 
     703        /* Increment index */ 
     704        geomval_ind->index++; 
     705 
     706        /* Clean up. Not really necessary */ 
     707        pfree(values[0]); 
     708        pfree(values[1]); 
     709        pfree(values[2]); 
     710        pfree(values); 
     711 
     712        SRF_RETURN_NEXT(funcctx, result); 
     713    } 
     714 
     715    /* No more left */ 
     716    else 
     717    { 
     718        /* Free geomval memory? */ 
     719 
     720        SRF_RETURN_DONE(funcctx); 
     721    } 
     722 
     723} 
     724 
     725#else 
     726PG_FUNCTION_INFO_V1(RASTER_asWKTPolygon); 
     727Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS) 
     728{ 
     729    /** 
     730     * This function is under development and may have an 
     731     * unexpected behaviour. If you want to use it, pass 
     732     * '--enable-development' option to configure script 
     733     */ 
     734 
     735    /* xxx jorgearevalo: The ereport call causes an error when a query is  
     736     * executed: 'errstart was not called'. I suppose is an initialization 
     737     * issue. Investigate it. 
     738     */ 
     739 
     740    /* 
     741    ereport(errcode(ERRCODE_WARNING), 
     742            (errmsg("This function is under development and may have an " 
     743                    "unexpected behaviour. If you want  to use it, pass " 
     744                    "--enable-development option to configure script"))); 
     745    */       
     746    PG_RETURN_NULL(); 
     747} 
     748#endif 
     749 
    519750 
    520751/** 
  • spike/wktraster/rt_pg/rtpostgis.sql.in.c

    r5502 r5516  
    5555); 
    5656 
     57CREATE TYPE geomval AS ( 
     58    geom geometry, 
     59    val double precision, 
     60    srid int 
     61); 
     62 
     63CREATE TYPE wktgeomval AS ( 
     64    wktgeom text, 
     65    val double precision, 
     66    srid int  
     67); 
     68 
    5769------------------------------------------------------------------------------ 
    5870--  FUNCTIONS 
     
    8294    RETURNS BOX2D 
    8395    AS 'MODULE_PATHNAME','RASTER_to_BOX2DFLOAT4' 
     96    LANGUAGE 'C' _IMMUTABLE_STRICT; 
     97 
     98CREATEFUNCTION DumpAsWKTPolygons(raster, int DEFAULT 1) 
     99    RETURNS SETOF wktgeomval 
     100    AS 'MODULE_PATHNAME','RASTER_dumpAsWKTPolygons' 
    84101    LANGUAGE 'C' _IMMUTABLE_STRICT; 
    85102 
     
    232249$$ 
    233250LANGUAGE 'plpgsql' _IMMUTABLE_STRICT; -- WITH (isstrict); 
     251 
    234252 
    235253CREATEFUNCTION st_setgeoreference(raster, text) 
     
    348366    AS 'MODULE_PATHNAME', 'RASTER_makeEmpty' 
    349367    LANGUAGE 'C' IMMUTABLE; -- a new lib will require a new session 
     368 
     369     
     370CREATEFUNCTION st_dumpaspolygons(raster)  
     371    RETURNS SETOF geomval 
     372    AS 'select st_geomfromtext(wktgeomval.wktgeom), wktgeomval.val, 
     373    wktgeomval.srid from dumpaswktpolygons($1, 1) as wktgeomval' 
     374    LANGUAGE 'SQL' _IMMUTABLE_STRICT; 
     375 
     376CREATEFUNCTION st_dumpaspolygons(raster, int)  
     377    RETURNS SETOF geomval 
     378    AS 'select st_geomfromtext(wktgeomval.wktgeom), wktgeomval.val, 
     379    wktgeomval.srid from dumpaswktpolygons($1, $2) as wktgeomval' 
     380    LANGUAGE 'SQL' _IMMUTABLE_STRICT; 
     381 
    350382 
    351383------------------------------------------------------------------------------ 
  • spike/wktraster/test/core/testapi.c

    r5482 r5516  
    10661066            int srid; 
    10671067            double val; 
    1068             char * wktPol; 
     1068            char * wktGeom; 
    10691069        }; 
    10701070 
    10711071        typedef struct rt_wktgeomval_t* rt_wktgeomval; 
    10721072         
    1073         rt_wktgeomval gv = rt_raster_as_wktpolygon(ctx, rt, 1); 
     1073        rt_wktgeomval gv = rt_raster_dump_as_wktpolygons(ctx, rt, 1); 
    10741074 
    10751075        CHECK_EQUALS(gv[0].val, 1); 
    1076         CHECK(!strcmp(gv[0].wktPol,"POLYGON ((3 1,3 2,2 2,2 3,1 3,1 6,2 6,2 7,3 7,3 8,5 8,5 6,3 6,3 3,4 3,5 3,5 1,3 1))")); 
     1076        CHECK(!strcmp(gv[0].wktGeom,"POLYGON ((3 1,3 2,2 2,2 3,1 3,1 6,2 6,2 7,3 7,3 8,5 8,5 6,3 6,3 3,4 3,5 3,5 1,3 1))")); 
    10771077 
    10781078        CHECK_EQUALS(gv[1].val, 2); 
    1079         CHECK(!strcmp(gv[1].wktPol,"POLYGON ((5 1,5 3,6 3,6 6,5 6,5 8,6 8,6 7,7 7,7 6,8 6,8 3,7 3,7 2,6 2,6 1,5 1))"));       
     1079        CHECK(!strcmp(gv[1].wktGeom,"POLYGON ((5 1,5 3,6 3,6 6,5 6,5 8,6 8,6 7,7 7,7 6,8 6,8 3,7 3,7 2,6 2,6 1,5 1))"));       
    10801080         
    10811081        rt_raster_destroy(ctx, rt);