pointcloud/pgsql/pc_editor.c
Éric Lemoine d552002187 Add PC_Transform
This commit adds a `PC_Transform` function that returns a new patch with its data transformed based on the passed `pcid`.

In contrast to `PC_SetPCId` this function may reinterpret the data if dimension interpretations, scales or offsets are different in the new schema. In the future `PC_Transform` will also re-project the patch data if the schema `srid` has changed, but that is not yet supported.
2017-04-26 16:46:40 +02:00

127 lines
2.9 KiB
C

/***********************************************************************
* pc_editor.c
*
* Editor functions for points and patches in PgSQL.
*
* Copyright (c) 2017 Oslandia
*
***********************************************************************/
#include "pc_pgsql.h" /* Common PgSQL support for our type */
Datum pcpatch_setpcid(PG_FUNCTION_ARGS);
Datum pcpatch_transform(PG_FUNCTION_ARGS);
static SERIALIZED_PATCH *
pcpatch_set_schema(SERIALIZED_PATCH *serpa,
PCSCHEMA *oschema, PCSCHEMA *nschema, float8 def)
{
SERIALIZED_PATCH *serpatch;
PCPATCH *paout;
if ( pc_schema_same_dimensions(oschema, nschema) )
{
// oschema and nschema have the same dimensions at the same
// positions, so we can take a fast path and avoid the
// point-by-point dimension-by-dimension copying
if ( oschema->compression == nschema->compression )
{
// no need to deserialize the patch
serpatch = palloc(serpa->size);
if ( ! serpatch )
return NULL;
memcpy(serpatch, serpa, serpa->size);
serpatch->pcid = nschema->pcid;
return serpatch;
}
else
{
paout = pc_patch_deserialize(serpa, oschema);
if ( ! paout )
return NULL;
paout->schema = nschema;
}
} else {
PCPATCH *patch;
patch = pc_patch_deserialize(serpa, oschema);
if ( ! patch )
return NULL;
paout = pc_patch_set_schema(patch, nschema, def);
if ( patch != paout )
pc_patch_free(patch);
if ( ! paout )
return NULL;
}
serpatch = pc_patch_serialize(paout, NULL);
pc_patch_free(paout);
return serpatch;
}
PG_FUNCTION_INFO_V1(pcpatch_setpcid);
Datum pcpatch_setpcid(PG_FUNCTION_ARGS)
{
SERIALIZED_PATCH *serpatch;
SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0);
int32 pcid = PG_GETARG_INT32(1);
float8 def = PG_GETARG_FLOAT8(2);
PCSCHEMA *oschema = pc_schema_from_pcid(serpa->pcid, fcinfo);
PCSCHEMA *nschema = pc_schema_from_pcid(pcid, fcinfo);
serpatch = pcpatch_set_schema(serpa, oschema, nschema, def);
if ( ! serpatch )
PG_RETURN_NULL();
PG_RETURN_POINTER(serpatch);
}
PG_FUNCTION_INFO_V1(pcpatch_transform);
Datum pcpatch_transform(PG_FUNCTION_ARGS)
{
SERIALIZED_PATCH *serpatch;
SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0);
int32 pcid = PG_GETARG_INT32(1);
float8 def = PG_GETARG_FLOAT8(2);
PCSCHEMA *oschema = pc_schema_from_pcid(serpa->pcid, fcinfo);
PCSCHEMA *nschema = pc_schema_from_pcid(pcid, fcinfo);
// fast path to setpcid if no data transformation is required
if ( pc_schema_same_interpretations(oschema, nschema) )
{
serpatch = pcpatch_set_schema(serpa, oschema, nschema, def);
if ( ! serpatch )
PG_RETURN_NULL();
PG_RETURN_POINTER(serpatch);
}
else
{
PCPATCH *patch, *paout;
patch = pc_patch_deserialize(serpa, oschema);
if ( ! patch )
PG_RETURN_NULL();
paout = pc_patch_transform(patch, nschema, def);
pc_patch_free(patch);
if ( ! paout )
PG_RETURN_NULL();
serpatch = pc_patch_serialize(paout, NULL);
pc_patch_free(paout);
PG_RETURN_POINTER(serpatch);
}
}