mirror of
https://github.com/pgpointcloud/pointcloud.git
synced 2025-12-08 20:36:04 +00:00
251 lines
6.4 KiB
C
251 lines
6.4 KiB
C
/***********************************************************************
|
|
* pc_patch_lazperf.c
|
|
*
|
|
* PgSQL Pointcloud is free and open source software provided
|
|
* by the Government of Canada
|
|
*
|
|
* Copyright (c) 2016 Paul Blottiere, Oslandia
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include "pc_api_internal.h"
|
|
#include "lazperf_adapter.h"
|
|
#include <assert.h>
|
|
|
|
void
|
|
pc_patch_lazperf_free(PCPATCH_LAZPERF *pal)
|
|
{
|
|
assert(pal);
|
|
pcfree(pal->lazperf);
|
|
pcfree(pal);
|
|
}
|
|
|
|
PCPATCH_LAZPERF *
|
|
pc_patch_lazperf_from_pointlist(const PCPOINTLIST *pdl)
|
|
{
|
|
PCPATCH_UNCOMPRESSED *patch = pc_patch_uncompressed_from_pointlist(pdl);
|
|
PCPATCH_LAZPERF *lazperfpatch = pc_patch_lazperf_from_uncompressed(patch);
|
|
pc_patch_free((PCPATCH*) patch);
|
|
|
|
return lazperfpatch;
|
|
}
|
|
|
|
PCPATCH_LAZPERF*
|
|
pc_patch_lazperf_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa)
|
|
{
|
|
#ifndef HAVE_LAZPERF
|
|
pcerror("%s: lazperf support is not enabled", __func__);
|
|
return NULL;
|
|
#endif
|
|
|
|
PCPATCH_LAZPERF *palaz = NULL;
|
|
uint8_t *compressed;
|
|
|
|
// cpp call to get compressed data from pcpatch
|
|
size_t compressSize = lazperf_compress_from_uncompressed(pa, &compressed);
|
|
|
|
if (compressSize != -1)
|
|
{
|
|
palaz = pcalloc(sizeof(PCPATCH_LAZPERF));
|
|
palaz->type = PC_LAZPERF;
|
|
palaz->readonly = PC_FALSE;
|
|
palaz->schema = pa->schema;
|
|
|
|
// not optimal but we have to pass by the context manager otherwise
|
|
// a segfault happenned (sometimes) during a pcfree of lazperf field
|
|
palaz->lazperf = (uint8_t*) pcalloc(compressSize);
|
|
memcpy(palaz->lazperf, compressed, compressSize);
|
|
free(compressed);
|
|
|
|
palaz->npoints = pa->npoints;
|
|
palaz->bounds = pa->bounds;
|
|
palaz->stats = pc_stats_clone(pa->stats);
|
|
palaz->lazperfsize = compressSize;
|
|
}
|
|
else
|
|
pcerror("%s: LAZ compressionf failed", __func__);
|
|
|
|
return palaz;
|
|
}
|
|
|
|
PCPOINTLIST *
|
|
pc_pointlist_from_lazperf(const PCPATCH_LAZPERF *palaz)
|
|
{
|
|
PCPATCH_UNCOMPRESSED *pu = NULL;
|
|
pu = pc_patch_uncompressed_from_lazperf(palaz);
|
|
PCPOINTLIST *pl = pc_pointlist_from_uncompressed(pu);
|
|
pl->mem = pc_patch_uncompressed_readonly(pu);
|
|
pc_patch_free((PCPATCH *)pu);
|
|
return pl;
|
|
}
|
|
|
|
PCPATCH_UNCOMPRESSED*
|
|
pc_patch_uncompressed_from_lazperf(const PCPATCH_LAZPERF *palaz)
|
|
{
|
|
#ifndef HAVE_LAZPERF
|
|
pcerror("%s: lazperf support is not enabled", __func__);
|
|
return NULL;
|
|
#endif
|
|
|
|
PCPATCH_UNCOMPRESSED *pcu = NULL;
|
|
uint8_t *decompressed;
|
|
|
|
// cpp call to uncompressed data
|
|
size_t size = lazperf_uncompress_from_compressed(palaz, &decompressed);
|
|
|
|
if (size != -1)
|
|
{
|
|
pcu = pcalloc(sizeof(PCPATCH_UNCOMPRESSED));
|
|
pcu->type = PC_NONE;
|
|
pcu->readonly = PC_FALSE;
|
|
pcu->schema = palaz->schema;
|
|
pcu->npoints = palaz->npoints;
|
|
pcu->bounds = palaz->bounds;
|
|
pcu->stats = pc_stats_clone(palaz->stats);
|
|
|
|
// not optimal but we have to pass by the context manager otherwise
|
|
// a segfault happenned (sometimes) during a pcfree of lazperf field
|
|
pcu->data = (uint8_t*) pcalloc(palaz->schema->size * palaz->npoints);
|
|
memcpy(pcu->data, decompressed, palaz->schema->size * palaz->npoints);
|
|
free(decompressed);
|
|
|
|
pcu->maxpoints = palaz->npoints;
|
|
}
|
|
else
|
|
pcerror("%s: lazperf uncompression failed", __func__);
|
|
|
|
return pcu;
|
|
}
|
|
|
|
char *
|
|
pc_patch_lazperf_to_string(const PCPATCH_LAZPERF *pa)
|
|
{
|
|
#ifndef HAVE_LAZPERF
|
|
pcerror("%s: lazperf support is not enabled", __func__);
|
|
return NULL;
|
|
#endif
|
|
PCPATCH_UNCOMPRESSED *patch = pc_patch_uncompressed_from_lazperf(pa);
|
|
char *str = pc_patch_uncompressed_to_string(patch);
|
|
pc_patch_free((PCPATCH*) patch);
|
|
return str;
|
|
}
|
|
|
|
uint8_t *
|
|
pc_patch_lazperf_to_wkb(const PCPATCH_LAZPERF *patch, size_t *wkbsize)
|
|
{
|
|
#ifndef HAVE_LAZPERF
|
|
pcerror("%s: lazperf support is not enabled", __func__);
|
|
return NULL;
|
|
#else
|
|
/*
|
|
byte: endianness (1 = NDR, 0 = XDR)
|
|
uint32: pcid (key to POINTCLOUD_SCHEMAS)
|
|
uint32: compression
|
|
uint32: npoints
|
|
uint32: lazperfsize
|
|
uint8[]: lazperfbuffer
|
|
*/
|
|
|
|
uint8_t *buf;
|
|
char endian = machine_endian();
|
|
/* endian + pcid + compression + npoints + lazperfsize + lazperf */
|
|
size_t size = 1 + 4 + 4 + 4 + 4 + patch->lazperfsize;
|
|
|
|
uint8_t *wkb = pcalloc(size);
|
|
uint32_t compression = patch->type;
|
|
uint32_t npoints = patch->npoints;
|
|
uint32_t pcid = patch->schema->pcid;
|
|
uint32_t lazperfsize = patch->lazperfsize;
|
|
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, &lazperfsize, 4); /* Write lazperf buffer size */
|
|
|
|
buf = wkb + 17;
|
|
memcpy(buf, patch->lazperf, patch->lazperfsize);
|
|
if (wkbsize)
|
|
*wkbsize = size;
|
|
|
|
return wkb;
|
|
#endif
|
|
}
|
|
|
|
PCPATCH *
|
|
pc_patch_lazperf_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize)
|
|
{
|
|
#ifndef HAVE_LAZPERF
|
|
pcerror("%s: lazperf 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: lazperfsize
|
|
uint8[]: lazerperfbuffer
|
|
*/
|
|
static size_t hdrsz = 1+4+4+4; /* endian + pcid + compression + npoints */
|
|
PCPATCH_LAZPERF *patch;
|
|
uint8_t swap_endian = (wkb[0] != machine_endian());
|
|
uint32_t npoints;
|
|
size_t lazperfsize;
|
|
const uint8_t *buf;
|
|
|
|
if (wkb_get_compression(wkb) != PC_LAZPERF)
|
|
{
|
|
pcerror("%s: call with wkb that is not LAZPERF compressed", __func__);
|
|
return NULL;
|
|
}
|
|
|
|
npoints = wkb_get_npoints(wkb);
|
|
|
|
patch = pcalloc(sizeof(PCPATCH_LAZPERF));
|
|
patch->type = PC_LAZPERF;
|
|
patch->readonly = PC_FALSE;
|
|
patch->schema = schema;
|
|
patch->npoints = npoints;
|
|
|
|
/* Start on the LAZPERF */
|
|
buf = wkb+hdrsz;
|
|
lazperfsize = wkb_get_int32(buf, swap_endian);
|
|
buf += 4;
|
|
|
|
/* Copy in the tree buffer */
|
|
patch->lazperfsize = lazperfsize;
|
|
patch->lazperf = pcalloc(lazperfsize);
|
|
memcpy(patch->lazperf, buf, lazperfsize);
|
|
|
|
return (PCPATCH*)patch;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
pc_patch_lazperf_compute_extent(PCPATCH_LAZPERF *patch)
|
|
{
|
|
#ifndef HAVE_LAZPERF
|
|
pcerror("%s: lazperf support is not enabled", __func__);
|
|
return PC_FAILURE;
|
|
#endif
|
|
|
|
PCPATCH_UNCOMPRESSED *pau = pc_patch_uncompressed_from_lazperf(patch);
|
|
return pc_patch_uncompressed_compute_extent(pau);
|
|
}
|
|
|
|
PCPOINT *
|
|
pc_patch_lazperf_pointn(const PCPATCH_LAZPERF *patch, int n)
|
|
{
|
|
#ifndef HAVE_LAZPERF
|
|
pcerror("%s: lazperf support is not enabled", __func__);
|
|
return NULL;
|
|
#endif
|
|
|
|
PCPOINT *pt = pc_point_make(patch->schema);
|
|
PCPATCH_UNCOMPRESSED *pau = pc_patch_uncompressed_from_lazperf(patch);
|
|
size_t size = patch->schema->size;
|
|
memcpy(pt->data, pau->data + n * size, size);
|
|
pc_patch_free((PCPATCH*) pau);
|
|
return pt;
|
|
}
|