Beispiel #1
0
uint8_t *
pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize)
{
	static uint32_t srid_mask = 0x20000000;
	static uint32_t z_mask = 0x80000000;
	uint32_t wkbtype = 1; /* WKB POINT */
	size_t size = 1 + 4 + 8 + 8; /* endian + type + dblX, + dblY */
	uint8_t *wkb, *ptr;
	uint32_t srid;
	int has_srid = PC_FALSE, has_z = PC_FALSE;
	double x, y, z;

	x = pc_point_get_x(pt);
	y = pc_point_get_y(pt);

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

	if ( pc_point_get_double_by_name(pt, "Z", &z) )
	{
		has_z = PC_TRUE;
		wkbtype |= z_mask;
		size += 8;
	}

	wkb = pcalloc(size);
	ptr = wkb;

	ptr[0] = machine_endian(); /* Endian flag */
	ptr += 1;

	memcpy(ptr, &wkbtype, 4); /* WKB type */
	ptr += 4;

	if ( has_srid )
	{
		memcpy(ptr, &srid, 4); /* SRID */
		ptr += 4;
	}

	memcpy(ptr, &x, 8); /* X */
	ptr += 8;

	memcpy(ptr, &y, 8); /* Y */
	ptr += 8;

	if ( has_z )
	{
		memcpy(ptr, &z, 8); /* Z */
		ptr += 8;
	}

	if ( wkbsize ) *wkbsize = size;
	return wkb;
}
uint8_t *
pc_patch_uncompressed_to_wkb(const PCPATCH_UNCOMPRESSED *patch, size_t *wkbsize)
{
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uint32:   compression (0 = no compression, 1 = dimensional, 2 = GHT)
	uint32:   npoints
	uchar[]:  data (interpret relative to pcid)
	*/
	char endian = machine_endian();
	/* endian + pcid + compression + npoints + datasize */
	size_t size = 1 + 4 + 4 + 4 + patch->datasize;
	uint8_t *wkb = pcalloc(size);
	uint32_t compression = patch->type;
	uint32_t npoints = patch->npoints;
	uint32_t pcid = patch->schema->pcid;
	wkb[0] = endian; /* Write endian flag */
	memcpy(wkb + 1, &pcid,        4); /* Write PCID */
	memcpy(wkb + 5, &compression, 4); /* Write compression */
	memcpy(wkb + 9, &npoints,     4); /* Write npoints */
	memcpy(wkb + 13, patch->data, patch->datasize); /* Write data */
	if ( wkbsize ) *wkbsize = size;
	return wkb;
}
Beispiel #3
0
/*
* Write an uncompressed patch out to hex
*/
static void
test_patch_hex_out()
{
	// 00 endian
	// 00000000 pcid
	// 00000000 compression
	// 00000002 npoints
	// 0000000200000003000000050006 pt1 (XYZi)
	// 0000000200000003000000050008 pt2 (XYZi)

	static char *wkt_result = "{\"pcid\":0,\"pts\":[[0.02,0.03,0.05,6],[0.02,0.03,0.05,8]]}";
	static char *hexresult_xdr =
	   "0000000000000000000000000200000002000000030000000500060000000200000003000000050008";
	static char *hexresult_ndr =
	   "0100000000000000000200000002000000030000000500000006000200000003000000050000000800";

	double d0[4] = { 0.02, 0.03, 0.05, 6 };
	double d1[4] = { 0.02, 0.03, 0.05, 8 };

	PCPOINT *pt0 = pc_point_from_double_array(simpleschema, d0, 4);
	PCPOINT *pt1 = pc_point_from_double_array(simpleschema, d1, 4);

	PCPATCH_UNCOMPRESSED *pa;
	uint8_t *wkb;
	size_t wkbsize;
	char *hexwkb;
	char *wkt;

	PCPOINTLIST *pl = pc_pointlist_make(2);
	pc_pointlist_add_point(pl, pt0);
	pc_pointlist_add_point(pl, pt1);

	pa = pc_patch_uncompressed_from_pointlist(pl);
	wkb = pc_patch_uncompressed_to_wkb(pa, &wkbsize);
	// printf("wkbsize %zu\n", wkbsize);
	hexwkb = hexbytes_from_bytes(wkb, wkbsize);

	// printf("hexwkb %s\n", hexwkb);
	// printf("hexresult_ndr %s\n", hexresult_ndr);
	// printf("machine_endian %d\n", machine_endian());
	if ( machine_endian() == PC_NDR )
	{
		CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_ndr);
	}
	else
	{
		CU_ASSERT_STRING_EQUAL(hexwkb, hexresult_xdr);
	}

	wkt = pc_patch_uncompressed_to_string(pa);
	// printf("wkt %s\n", wkt);
	CU_ASSERT_STRING_EQUAL(wkt, wkt_result);

	pc_patch_free((PCPATCH*)pa);
	pc_pointlist_free(pl);
	pcfree(hexwkb);
	pcfree(wkb);
	pcfree(wkt);
}
PCPATCH *
pc_patch_uncompressed_from_wkb(const PCSCHEMA *s, const uint8_t *wkb, size_t wkbsize)
{
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uint32:   compression (0 = no compression, 1 = dimensional, 2 = lazperf)
	uint32:   npoints
	pcpoint[]:  data (interpret relative to pcid)
	*/
	static size_t hdrsz = 1+4+4+4; /* endian + pcid + compression + npoints */
	PCPATCH_UNCOMPRESSED *patch;
	uint8_t *data;
	uint8_t swap_endian = (wkb[0] != machine_endian());
	uint32_t npoints;

	if ( wkb_get_compression(wkb) != PC_NONE )
	{
		pcerror("%s: call with wkb that is not uncompressed", __func__);
		return NULL;
	}

	npoints = wkb_get_npoints(wkb);
	if ( (wkbsize - hdrsz) != (s->size * npoints) )
	{
		pcerror("%s: wkb size and expected data size do not match", __func__);
		return NULL;
	}

	if ( swap_endian )
	{
		data = uncompressed_bytes_flip_endian(wkb+hdrsz, s, npoints);
	}
	else
	{
		data = pcalloc(npoints * s->size);
		memcpy(data, wkb+hdrsz, npoints*s->size);
	}

	patch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED));
	patch->type = PC_NONE;
	patch->readonly = PC_FALSE;
	patch->schema = s;
	patch->npoints = npoints;
	patch->maxpoints = npoints;
	patch->datasize = (wkbsize - hdrsz);
	patch->data = data;
	patch->stats = NULL;

	return (PCPATCH*)patch;
}
PCPATCH *
pc_patch_ght_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize)
{
#ifndef HAVE_LIBGHT
	pcerror("%s: libght support is not enabled", __func__);
	return NULL;
#else
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uint32:   compression (0 = no compression, 1 = dimensional, 2 = GHT)
	uint32:   npoints
	uint32:   ghtsize
	uint8[]:  ghtbuffer
	*/
	static size_t hdrsz = 1+4+4+4; /* endian + pcid + compression + npoints */
	PCPATCH_GHT *patch;
	uint8_t swap_endian = (wkb[0] != machine_endian());
	uint32_t npoints;
	size_t ghtsize;
	const uint8_t *buf;

	if ( wkb_get_compression(wkb) != PC_GHT )
	{
		pcerror("%s: call with wkb that is not GHT compressed", __func__);
		return NULL;
	}

	npoints = wkb_get_npoints(wkb);

	patch = pcalloc(sizeof(PCPATCH_GHT));
	patch->type = PC_GHT;
	patch->readonly = PC_FALSE;
	patch->schema = schema;
	patch->npoints = npoints;

	/* Start on the GHT */
	buf = wkb+hdrsz;
	ghtsize = wkb_get_int32(buf, swap_endian);
	buf += 4; /* Move to start of GHT buffer */

	/* Copy in the tree buffer */
	patch->ght = pcalloc(ghtsize);
	patch->ghtsize = ghtsize;
	memcpy(patch->ght, buf, ghtsize);

	return (PCPATCH*)patch;
#endif
}
Beispiel #6
0
uint32_t
wkb_get_pcid(const uint8_t *wkb)
{
	/* We expect the bytes to be in WKB format for PCPOINT/PCPATCH */
	/* byte 0:   endian */
	/* byte 1-4: pcid */
	/* ...data... */
	uint32_t pcid;
	memcpy(&pcid, wkb + 1, 4);
	if ( wkb[0] != machine_endian() )
	{
		pcid = int32_flip_endian(pcid);
	}
	return pcid;
}
Beispiel #7
0
uint32_t
wkb_get_compression(const uint8_t *wkb)
{
	/* We expect the bytes to be in WKB format for PCPATCH */
	/* byte 0:   endian */
	/* byte 1-4: pcid */
	/* byte 5-8: compression */
	/* ...data... */
	uint32_t compression;
	memcpy(&compression, wkb+1+4, 4);
	if ( wkb[0] != machine_endian() )
	{
		compression = int32_flip_endian(compression);
	}
	return compression;
}
Beispiel #8
0
uint32_t
wkb_get_npoints(const uint8_t *wkb)
{
	/* We expect the bytes to be in WKB format for PCPATCH */
	/* byte 0:   endian */
	/* byte 1-4: pcid */
	/* byte 5-8: compression */
	/* byte 9-12: npoints */
	/* ...data... */
	uint32_t npoints;
	memcpy(&npoints, wkb+1+4+4, 4);
	if ( wkb[0] != machine_endian() )
	{
		npoints = int32_flip_endian(npoints);
	}
	return npoints;
}
Beispiel #9
0
uint8_t *
pc_point_to_wkb(const PCPOINT *pt, size_t *wkbsize)
{
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uchar[]:  data (interpret relative to pcid)
	*/
	char endian = machine_endian();
	size_t size = 1 + 4 + pt->schema->size;
	uint8_t *wkb = pcalloc(size);
	wkb[0] = endian; /* Write endian flag */
	memcpy(wkb + 1, &(pt->schema->pcid), 4); /* Write PCID */
	memcpy(wkb + 5, pt->data, pt->schema->size); /* Write data */
	if ( wkbsize ) *wkbsize = size;
	return wkb;
}
PCPATCH *
pc_patch_dimensional_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize)
{
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uint32:   compression (0 = no compression, 1 = dimensional, 2 = GHT)
	uint32:   npoints
	dimensions[]:  dims (interpret relative to pcid and compressions)
	*/
	static size_t hdrsz = 1+4+4+4; /* endian + pcid + compression + npoints */
	PCPATCH_DIMENSIONAL *patch;
	uint8_t swap_endian = (wkb[0] != machine_endian());
	uint32_t npoints, ndims;
	const uint8_t *buf;
	int i;

	if ( wkb_get_compression(wkb) != PC_DIMENSIONAL )
	{
		pcerror("%s: call with wkb that is not dimensionally compressed", __func__);
		return NULL;
	}

	npoints = wkb_get_npoints(wkb);
	ndims = schema->ndims;

	patch = pcalloc(sizeof(PCPATCH_DIMENSIONAL));
	patch->type = PC_DIMENSIONAL;
	patch->readonly = PC_FALSE;
	patch->schema = schema;
	patch->npoints = npoints;
	patch->bytes = pcalloc(ndims*sizeof(PCBYTES));

	buf = wkb+hdrsz;
	for ( i = 0; i < ndims; i++ )
	{
		PCBYTES *pcb = &(patch->bytes[i]);
		PCDIMENSION *dim = schema->dims[i];
		pc_bytes_deserialize(buf, dim, pcb, PC_FALSE /*readonly*/, swap_endian);
		pcb->npoints = npoints;
		buf += pc_bytes_serialized_size(pcb);
	}

	return (PCPATCH*)patch;
}
Beispiel #11
0
PCPOINT *
pc_point_from_wkb(const PCSCHEMA *schema, uint8_t *wkb, size_t wkblen)
{
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uchar[]:  data (interpret relative to pcid)
	*/
	const size_t hdrsz = 1+4; /* endian + pcid */
	uint8_t wkb_endian;
	uint32_t pcid;
	uint8_t *data;
	PCPOINT *pt;

	if ( ! wkblen )
	{
		pcerror("pc_point_from_wkb: zero length wkb");
	}

	wkb_endian = wkb[0];
	pcid = wkb_get_pcid(wkb);

	if ( (wkblen-hdrsz) != schema->size )
	{
		pcerror("pc_point_from_wkb: wkb size inconsistent with schema size");
	}

	if ( wkb_endian != machine_endian() )
	{
		/* uncompressed_bytes_flip_endian creates a flipped copy */
		data = uncompressed_bytes_flip_endian(wkb+hdrsz, schema, 1);
	}
	else
	{
		data = pcalloc(schema->size);
		memcpy(data, wkb+hdrsz, wkblen-hdrsz);
	}

	pt = pc_point_from_data(schema, data);
	pt->readonly = PC_FALSE;
	return pt;
}
uint8_t *
pc_patch_dimensional_to_wkb(const PCPATCH_DIMENSIONAL *patch, size_t *wkbsize)
{
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uint32:   compression (0 = no compression, 1 = dimensional, 2 = GHT)
	uint32:   npoints
	dimensions[]:  pcbytes (interpret relative to pcid and compressions)
	*/
	int ndims = patch->schema->ndims;
	int i;
	uint8_t *buf;
	char endian = machine_endian();
	/* endian + pcid + compression + npoints + datasize */
	size_t size = 1 + 4 + 4 + 4 + pc_patch_dimensional_serialized_size(patch);
	uint8_t *wkb = pcalloc(size);
	uint32_t compression = patch->type;
	uint32_t npoints = patch->npoints;
	uint32_t pcid = patch->schema->pcid;
	wkb[0] = endian; /* Write endian flag */
	memcpy(wkb + 1, &pcid,        4); /* Write PCID */
	memcpy(wkb + 5, &compression, 4); /* Write compression */
	memcpy(wkb + 9, &npoints,     4); /* Write npoints */

	buf = wkb + 13;
	for ( i = 0; i < ndims; i++ )
	{
		size_t bsz;
		PCBYTES *pcb = &(patch->bytes[i]);
// XXX        printf("pcb->(size=%d, interp=%d, npoints=%d, compression=%d, readonly=%d)\n",pcb->size, pcb->interpretation, pcb->npoints, pcb->compression, pcb->readonly);

		pc_bytes_serialize(pcb, buf, &bsz);
		buf += bsz;
	}

	if ( wkbsize ) *wkbsize = size;
	return wkb;
}
Beispiel #13
0
uint8_t *
pc_patch_ght_to_wkb(const PCPATCH_GHT *patch, size_t *wkbsize)
{
#ifndef HAVE_LIBGHT
	pcerror("%s: libght support is not enabled", __func__);
	return NULL;
#else
	/*
	byte:     endianness (1 = NDR, 0 = XDR)
	uint32:   pcid (key to POINTCLOUD_SCHEMAS)
	uint32:   compression (0 = no compression, 1 = dimensional, 2 = GHT)
	uint32:   npoints
	uint32:   ghtsize
	uint8[]:  ghtbuffer
	*/

	uint8_t *buf;
	char endian = machine_endian();
	/* endian + pcid + compression + npoints + ghtsize + ght */
	size_t size = 1 + 4 + 4 + 4 + 4 + patch->ghtsize;

	uint8_t *wkb = pcalloc(size);
	uint32_t compression = patch->type;
	uint32_t npoints = patch->npoints;
	uint32_t pcid = patch->schema->pcid;
	uint32_t ghtsize = patch->ghtsize;
	wkb[0] = endian; /* Write endian flag */
	memcpy(wkb +  1, &pcid,        4); /* Write PCID */
	memcpy(wkb +  5, &compression, 4); /* Write compression */
	memcpy(wkb +  9, &npoints,     4); /* Write npoints */
	memcpy(wkb + 13, &ghtsize,     4); /* Write ght buffer size */

	buf = wkb + 17;
	memcpy(buf, patch->ght, patch->ghtsize);
	if ( wkbsize ) *wkbsize = size;
	return wkb;
#endif
}
Beispiel #14
0
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;
}
Beispiel #15
0
uint8_t *
pc_point_to_geometry_wkb(const PCPOINT *pt, size_t *wkbsize)
{
	static uint32_t srid_mask = 0x20000000;
	static uint32_t m_mask = 0x40000000;
	static uint32_t z_mask = 0x80000000;
	uint32_t wkbtype = 1; /* WKB POINT */
	size_t size = 1 + 4 + 8 + 8; /* endian + type + dblX, + dblY */
	uint8_t *wkb, *ptr;
	uint32_t srid = pt->schema->srid;
	double x, y, z, m;
	int has_x = pc_point_get_x(pt, &x) == PC_SUCCESS;
	int has_y = pc_point_get_y(pt, &y) == PC_SUCCESS;
	int has_z = pc_point_get_z(pt, &z) == PC_SUCCESS;
	int has_m = pc_point_get_m(pt, &m) == PC_SUCCESS;

	if ( ! ( has_x && has_y ) )
		return NULL;

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

	if ( has_z )
	{
		wkbtype |= z_mask;
		size += 8;
	}

	if ( has_m )
	{
		wkbtype |= m_mask;
		size += 8;
	}

	wkb = pcalloc(size);
	ptr = wkb;

	ptr[0] = machine_endian(); /* Endian flag */
	ptr += 1;

	memcpy(ptr, &wkbtype, 4); /* WKB type */
	ptr += 4;

	if ( srid != 0 )
	{
		memcpy(ptr, &srid, 4); /* SRID */
		ptr += 4;
	}

	memcpy(ptr, &x, 8); /* X */
	ptr += 8;

	memcpy(ptr, &y, 8); /* Y */
	ptr += 8;

	if ( has_z )
	{
		memcpy(ptr, &z, 8); /* Z */
		ptr += 8;
	}

	if ( has_m )
	{
		memcpy(ptr, &m, 8); /* M */
		ptr += 8;
	}

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