Skip to content

Commit

Permalink
pc_bounds_to_geometry_wkb
Browse files Browse the repository at this point in the history
  • Loading branch information
mbredif committed Aug 30, 2018
1 parent 29fdb7c commit ed5451f
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 106 deletions.
22 changes: 19 additions & 3 deletions lib/cunit/cu_pc_patch.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,12 @@ test_patch_wkb()
PCPOINTLIST *pl1;
PCPATCH_UNCOMPRESSED *pu1, *pu2;
PCPATCH *pa1, *pa2, *pa3, *pa4;
size_t z1, z2;
uint8_t *wkb1, *wkb2;
size_t z1, z2, z3;
uint8_t *wkb1, *wkb2, *wkb3;
char *hexwkb;

static char *hexresult_ndr = "01030000000100000005000000000000000000000000000000000000000000000000000000CDCCCCCCCC8C4B40EC51B81E852B4440CDCCCCCCCC8C4B40EC51B81E852B4440000000000000000000000000000000000000000000000000";
static char *hexresult_xdr = "00000000030000000100000005000000000000000000000000000000000000000000000000404B8CCCCCCCCCCD40442B851EB851EC404B8CCCCCCCCCCD40442B851EB851EC000000000000000000000000000000000000000000000000";

pl1 = pc_pointlist_make(npts);

Expand All @@ -533,6 +537,7 @@ test_patch_wkb()
// str = pc_hexbytes_from_bytes(wkb1, z1);
// printf("str\n%s\n",str);
pa2 = pc_patch_from_wkb(simpleschema, wkb1, z1);
pcfree(wkb1);

// printf("pa2\n%s\n",pc_patch_to_string(pa2));

Expand All @@ -556,6 +561,18 @@ test_patch_wkb()
CU_ASSERT_EQUAL(pu1->npoints, pu2->npoints);
CU_ASSERT(memcmp(pu1->data, pu2->data, pu1->datasize) == 0);

wkb3 = pc_bounds_to_geometry_wkb(&pa1->bounds, simpleschema->srid, &z3);
hexwkb = pc_hexbytes_from_bytes(wkb3, z3);
if ( machine_endian() == PC_NDR )
{
CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_ndr);
}
else
{
CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_xdr);
}
pcfree(hexwkb);
pcfree(wkb3);

pc_pointlist_free(pl1);
pc_patch_free(pa1);
Expand All @@ -564,7 +581,6 @@ test_patch_wkb()
pc_patch_free(pa4);
pc_patch_free((PCPATCH*)pu1);
pc_patch_free((PCPATCH*)pu2);
pcfree(wkb1);
}


Expand Down
3 changes: 3 additions & 0 deletions lib/pc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,9 @@ int pc_patch_compute_extent(PCPATCH *patch);
/** True/false if bounds intersect */
int pc_bounds_intersects(const PCBOUNDS *b1, const PCBOUNDS *b2);

/** Return the bounds as an OGC WKB geometry */
uint8_t *pc_bounds_to_geometry_wkb(const PCBOUNDS *bounds, uint32_t srid, size_t *wkbsize);

/** Returns OGC WKB of the bounding diagonal of XY bounds */
uint8_t* pc_bounding_diagonal_wkb_from_bounds(const PCBOUNDS *bounds, const PCSCHEMA *schema, size_t *wkbsize);

Expand Down
77 changes: 77 additions & 0 deletions lib/pc_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,83 @@ static uint32_t srid_mask = 0x20000000;
static uint32_t m_mask = 0x40000000;
static uint32_t z_mask = 0x80000000;

uint8_t *
pc_bounds_to_geometry_wkb(const PCBOUNDS *bounds, uint32_t srid, size_t *wkbsize)
{
/* Bounds! */
double xmin = bounds->xmin;
double ymin = bounds->ymin;
double xmax = bounds->xmax;
double ymax = bounds->ymax;

static uint32_t srid_mask = 0x20000000;
static uint32_t npoints_by_type[] = { 0, 1, 2, 5 };
/* WKB POINT, LINESTRING or POLYGON */
uint32_t wkbtype = 1 + (xmin != xmax) + (ymin != ymax);
uint32_t npoints = npoints_by_type[wkbtype];
uint8_t *wkb, *ptr;
/* endian + (type + nrings? + npoints?) + npoints dbl pt */
size_t size = 1 + wkbtype * 4 + npoints * 2 * 8;

if ( srid )
{
wkbtype |= srid_mask;
size += 4;
}

wkb = pcalloc(size);
ptr = wkb;

ptr = wkb_set_char(ptr, machine_endian()); /* Endian flag */

ptr = wkb_set_uint32(ptr, wkbtype); /* TYPE = POINT, LINESTRING or POLYGON */

if ( srid )
{
ptr = wkb_set_uint32(ptr, srid); /* SRID */
}

switch ( wkbtype )
{
case 3 /* POLYGON */ : ptr = wkb_set_uint32(ptr, 1); /* NRINGS */
case 2 /* LINESTRING */ : ptr = wkb_set_uint32(ptr, npoints); /* NPOINTS */
}

/* Point 0 */
ptr = wkb_set_double(ptr, xmin);
ptr = wkb_set_double(ptr, ymin);

if ( wkbtype == 2 ) // LINESTRING
{
/* Point 1 */
ptr = wkb_set_double(ptr, xmax);
ptr = wkb_set_double(ptr, ymax);
}
else if( wkbtype == 3 ) // POLYGON
{
/* Point 1 */
ptr = wkb_set_double(ptr, xmin);
ptr = wkb_set_double(ptr, ymax);

/* Point 2 */
ptr = wkb_set_double(ptr, xmax);
ptr = wkb_set_double(ptr, ymax);

/* Point 3 */
ptr = wkb_set_double(ptr, xmax);
ptr = wkb_set_double(ptr, ymin);

/* Point 4 */
ptr = wkb_set_double(ptr, xmin);
ptr = wkb_set_double(ptr, ymin);
}

if ( wkbsize )
*wkbsize = size;

return wkb;
}

uint8_t *
pc_bounding_diagonal_wkb_from_bounds(
const PCBOUNDS *bounds, const PCSCHEMA *schema, size_t *wkbsize)
Expand Down
4 changes: 2 additions & 2 deletions pgsql/pc_inout.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,13 @@ Datum pcpatch_envelope_as_bytea(PG_FUNCTION_ARGS)
SERIALIZED_PATCH *serpatch = PG_GETHEADER_SERPATCH_P(0);
PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo);

bytes = pc_patch_to_geometry_wkb_envelope(serpatch, schema, &bytes_size);
bytes = pc_bounds_to_geometry_wkb(&serpatch->bounds, schema->srid, &bytes_size);
wkb_size = VARHDRSZ + bytes_size;
wkb = palloc(wkb_size);
memcpy(VARDATA(wkb), bytes, bytes_size);
SET_VARSIZE(wkb, wkb_size);

pfree(bytes);
pcfree(bytes);

PG_RETURN_BYTEA_P(wkb);
}
Expand Down
101 changes: 0 additions & 101 deletions pgsql/pc_pgsql.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,104 +847,3 @@ pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema)
pcerror("%s: unsupported compression type", __func__);
return NULL;
}


static uint8_t *
pc_patch_wkb_set_double(uint8_t *wkb, double d)
{
memcpy(wkb, &d, 8);
wkb += 8;
return wkb;
}

static uint8_t *
pc_patch_wkb_set_int32(uint8_t *wkb, uint32_t i)
{
memcpy(wkb, &i, 4);
wkb += 4;
return wkb;
}

static uint8_t *
pc_patch_wkb_set_char(uint8_t *wkb, char c)
{
memcpy(wkb, &c, 1);
wkb += 1;
return wkb;
}

/* 0 = xdr | big endian */
/* 1 = ndr | little endian */
static char
machine_endian(void)
{
static int check_int = 1; /* dont modify this!!! */
return *((char *) &check_int);
}

uint8_t *
pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, const PCSCHEMA *schema, size_t *wkbsize)
{
static uint32_t srid_mask = 0x20000000;
static uint32_t nrings = 1;
static uint32_t npoints = 5;
uint32_t wkbtype = 3; /* WKB POLYGON */
uint8_t *wkb, *ptr;
int has_srid = false;
size_t size = 1 + 4 + 4 + 4 + 2*npoints*8; /* endian + type + nrings + npoints + 5 dbl pts */

/* Bounds! */
double xmin = pa->bounds.xmin;
double ymin = pa->bounds.ymin;
double xmax = pa->bounds.xmax;
double ymax = pa->bounds.ymax;

/* Make sure they're slightly bigger than a point */
if ( xmin == xmax ) xmax += xmax * 0.0000001;
if ( ymin == ymax ) ymax += ymax * 0.0000001;

if ( schema->srid > 0 )
{
has_srid = true;
wkbtype |= srid_mask;
size += 4;
}

wkb = palloc(size);
ptr = wkb;

ptr = pc_patch_wkb_set_char(ptr, machine_endian()); /* Endian flag */

ptr = pc_patch_wkb_set_int32(ptr, wkbtype); /* TYPE = Polygon */

if ( has_srid )
{
ptr = pc_patch_wkb_set_int32(ptr, schema->srid); /* SRID */
}

ptr = pc_patch_wkb_set_int32(ptr, nrings); /* NRINGS = 1 */
ptr = pc_patch_wkb_set_int32(ptr, npoints); /* NPOINTS = 5 */

/* Point 0 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin);

/* Point 1 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax);

/* Point 2 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax);

/* Point 3 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin);

/* Point 4 */
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin);
ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin);

if ( wkbsize ) *wkbsize = size;
return wkb;
}

0 comments on commit ed5451f

Please sign in to comment.