Changeset 5516
- Timestamp:
- 04/09/10 06:34:35 (2 years ago)
- Location:
- spike/wktraster
- Files:
-
- 5 modified
-
rt_core/rt_api.c (modified) (9 diffs)
-
rt_core/rt_api.h (modified) (1 diff)
-
rt_pg/rt_pg.c (modified) (2 diffs)
-
rt_pg/rtpostgis.sql.in.c (modified) (4 diffs)
-
test/core/testapi.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
spike/wktraster/rt_core/rt_api.c
r5482 r5516 1313 1313 int srid; 1314 1314 double val; 1315 char * wkt Pol;1315 char * wktGeom; 1316 1316 }; 1317 1317 … … 1319 1319 #ifdef ENABLE_DEVELOPMENT 1320 1320 rt_wktgeomval 1321 rt_raster_ as_wktpolygon(rt_context ctx, rt_raster raster, int nband)1321 rt_raster_dump_as_wktpolygons(rt_context ctx, rt_raster raster, int nband) 1322 1322 { 1323 1323 char szDataPointer[50]; … … 1405 1405 memdataset = GDALCreate(GDALGetDriverByName("MEM"), 1406 1406 "",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); 1409 1409 1410 1410 if (NULL == memdataset) … … 1596 1596 1597 1597 /** 1598 * The field was stored as int, but we can use this function because1599 * uses "atof" to transform the string representation of the number1600 * into a double. We shouldn't have problems1598 * 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 1601 1601 **/ 1602 1602 dValueToCompare = OGR_F_GetFieldAsDouble(hFeature, iPixVal); … … 1607 1607 * the associated polygon is discarded 1608 1608 **/ 1609 dEpsilon = fabs(dValueToCompare - dBandNoData);1610 if (dEpsilon > FLT_EPSILON)1609 dEpsilon = fabs(dValueToCompare - dBandNoData); 1610 if (dEpsilon > FLT_EPSILON) 1611 1611 nValidPols--; 1612 1612 } … … 1630 1630 dEpsilon = fabs(dValueToCompare - dBandNoData); 1631 1631 1632 / / Valid polygon1632 /* Valid polygon */ 1633 1633 if (dEpsilon > FLT_EPSILON) 1634 1634 { … … 1636 1636 OGR_G_ExportToWkt(hGeom, &pszSrcText); 1637 1637 1638 / / Fill rt_wktgeomval structure1638 /* Fill rt_wktgeomval structure */ 1639 1639 pols[nCont].val = OGR_F_GetFieldAsInteger(hFeature, iPixVal); 1640 1640 pols[nCont].srid = rt_raster_get_srid(ctx, raster); 1641 pols[nCont].wkt Pol= (char *)ctx->alloc(strlen(pszSrcText)1641 pols[nCont].wktGeom = (char *)ctx->alloc(strlen(pszSrcText) 1642 1642 * sizeof(char)); 1643 strcpy(pols[nCont].wkt Pol, pszSrcText);1644 1645 #ifdef POSTGIS_RASTER_API_DEBUG 1646 ctx->info("Feature %d, WKT Polygon: %s", j, pols[nCont].wkt Pol);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); 1647 1647 ctx->info("Feature %d, value: %d", j, (int)(pols[nCont].val)); 1648 1648 ctx->info("Feature %d, srid: %d", j, pols[nCont].srid); … … 1666 1666 1667 1667 rt_wktgeomval 1668 rt_raster_ as_wktpolygon(rt_context ctx, rt_raster raster, int nband)1668 rt_raster_dump_as_wktpolygons(rt_context ctx, rt_raster raster, int nband) 1669 1669 { 1670 1670 /** … … 1676 1676 } 1677 1677 1678 #endif / / ENABLE_DEVELOPMENT1678 #endif /* ENABLE_DEVELOPMENT */ 1679 1679 1680 1680 -
spike/wktraster/rt_core/rt_api.h
r5425 r5516 542 542 */ 543 543 rt_wktgeomval 544 rt_raster_ as_wktpolygon(rt_context ctx, rt_raster raster, int nband);544 rt_raster_dump_as_wktpolygons(rt_context ctx, rt_raster raster, int nband); 545 545 546 546 /** -
spike/wktraster/rt_pg/rt_pg.c
r5500 r5516 88 88 Datum RASTER_to_LWGEOM(PG_FUNCTION_ARGS); 89 89 Datum RASTER_to_BOX2DFLOAT4(PG_FUNCTION_ARGS); 90 Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS); 90 91 91 92 /* Get all the properties of a raster */ … … 517 518 PG_RETURN_POINTER(bbox); 518 519 } 520 521 522 523 524 /** 525 * Needed for sizeof 526 */ 527 struct 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 539 struct rt_wktgeomval_ind_t { 540 rt_wktgeomval geomval; 541 int index; 542 }; 543 544 typedef 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 */ 553 PG_FUNCTION_INFO_V1(RASTER_asWKTPolygon); 554 Datum 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 726 PG_FUNCTION_INFO_V1(RASTER_asWKTPolygon); 727 Datum 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 519 750 520 751 /** -
spike/wktraster/rt_pg/rtpostgis.sql.in.c
r5502 r5516 55 55 ); 56 56 57 CREATE TYPE geomval AS ( 58 geom geometry, 59 val double precision, 60 srid int 61 ); 62 63 CREATE TYPE wktgeomval AS ( 64 wktgeom text, 65 val double precision, 66 srid int 67 ); 68 57 69 ------------------------------------------------------------------------------ 58 70 -- FUNCTIONS … … 82 94 RETURNS BOX2D 83 95 AS 'MODULE_PATHNAME','RASTER_to_BOX2DFLOAT4' 96 LANGUAGE 'C' _IMMUTABLE_STRICT; 97 98 CREATEFUNCTION DumpAsWKTPolygons(raster, int DEFAULT 1) 99 RETURNS SETOF wktgeomval 100 AS 'MODULE_PATHNAME','RASTER_dumpAsWKTPolygons' 84 101 LANGUAGE 'C' _IMMUTABLE_STRICT; 85 102 … … 232 249 $$ 233 250 LANGUAGE 'plpgsql' _IMMUTABLE_STRICT; -- WITH (isstrict); 251 234 252 235 253 CREATEFUNCTION st_setgeoreference(raster, text) … … 348 366 AS 'MODULE_PATHNAME', 'RASTER_makeEmpty' 349 367 LANGUAGE 'C' IMMUTABLE; -- a new lib will require a new session 368 369 370 CREATEFUNCTION 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 376 CREATEFUNCTION 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 350 382 351 383 ------------------------------------------------------------------------------ -
spike/wktraster/test/core/testapi.c
r5482 r5516 1066 1066 int srid; 1067 1067 double val; 1068 char * wkt Pol;1068 char * wktGeom; 1069 1069 }; 1070 1070 1071 1071 typedef struct rt_wktgeomval_t* rt_wktgeomval; 1072 1072 1073 rt_wktgeomval gv = rt_raster_ as_wktpolygon(ctx, rt, 1);1073 rt_wktgeomval gv = rt_raster_dump_as_wktpolygons(ctx, rt, 1); 1074 1074 1075 1075 CHECK_EQUALS(gv[0].val, 1); 1076 CHECK(!strcmp(gv[0].wkt Pol,"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))")); 1077 1077 1078 1078 CHECK_EQUALS(gv[1].val, 2); 1079 CHECK(!strcmp(gv[1].wkt Pol,"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))")); 1080 1080 1081 1081 rt_raster_destroy(ctx, rt);
