Example #1
0
/**
* Peak into a #GSERIALIZED datum to find the bounding box. If the
* box is there, copy it out and return it. If not, calculate the box from the
* full object and return the box based on that. If no box is available,
* return #LW_FAILURE, otherwise #LW_SUCCESS.
*/
int 
gserialized_datum_get_gidx_p(Datum gsdatum, GIDX *gidx)
{
	GSERIALIZED *gpart;
	int result = LW_SUCCESS;

	POSTGIS_DEBUG(4, "entered function");

	/*
	** The most info we need is the 8 bytes of serialized header plus the 32 bytes
	** of floats necessary to hold the 8 floats of the largest XYZM index
	** bounding box, so 40 bytes.
	*/
	gpart = (GSERIALIZED*)PG_DETOAST_DATUM_SLICE(gsdatum, 0, 40);

	POSTGIS_DEBUGF(4, "got flags %d", gpart->flags);

	/* Do we even have a serialized bounding box? */
	if ( FLAGS_GET_BBOX(gpart->flags) )
	{
		/* Yes! Copy it out into the GIDX! */
		size_t size = gbox_serialized_size(gpart->flags);
		POSTGIS_DEBUG(4, "copying box out of serialization");
		memcpy(gidx->c, gpart->data, size);
		/* if M is present but Z is not, pad Z and shift M */
		if ( FLAGS_GET_M(gpart->flags) && ! FLAGS_GET_Z(gpart->flags) )
		{
			size += 2 * sizeof(float);
			GIDX_SET_MIN(gidx,3,GIDX_GET_MIN(gidx,2));
			GIDX_SET_MAX(gidx,3,GIDX_GET_MAX(gidx,2));
			GIDX_SET_MIN(gidx,2,-1*FLT_MAX);
			GIDX_SET_MAX(gidx,2,FLT_MAX);
		}
		SET_VARSIZE(gidx, VARHDRSZ + size);
		result = LW_SUCCESS;
	}
	else
	{
		/* No, we need to calculate it from the full object. */
		GSERIALIZED *g = (GSERIALIZED*)PG_DETOAST_DATUM(gsdatum);
		LWGEOM *lwgeom = lwgeom_from_gserialized(g);
		GBOX gbox;
		if ( lwgeom_calculate_gbox(lwgeom, &gbox) == LW_FAILURE )
		{
			POSTGIS_DEBUG(4, "could not calculate bbox, returning failure");
			lwgeom_free(lwgeom);
			return LW_FAILURE;
		}
		lwgeom_free(lwgeom);
		result = gidx_from_gbox_p(gbox, gidx);
	}
	
	if ( result == LW_SUCCESS )
	{
		POSTGIS_DEBUGF(4, "got gidx %s", gidx_to_string(gidx));
	}

	return result;
}
/* Enlarge b_union to contain b_new. If b_new contains more
   dimensions than b_union, expand b_union to contain those dimensions. */
static void gidx_merge(GIDX **b_union, GIDX *b_new)
{
	int i, dims_union, dims_new;
	Assert(b_union);
	Assert(*b_union);
	Assert(b_new);

	dims_union = GIDX_NDIMS(*b_union);
	dims_new = GIDX_NDIMS(b_new);

	POSTGIS_DEBUGF(4, "merging gidx (%s) into gidx (%s)", gidx_to_string(b_new), gidx_to_string(*b_union));

	if ( dims_new > dims_union )
	{
		POSTGIS_DEBUGF(5, "reallocating b_union from %d dims to %d dims", dims_union, dims_new);
		*b_union = (GIDX*)repalloc(*b_union, GIDX_SIZE(dims_new));
		SET_VARSIZE(*b_union, VARSIZE(b_new));
		dims_union = dims_new;
	}

	for ( i = 0; i < dims_new; i++ )
	{
		/* Adjust minimums */
		GIDX_SET_MIN(*b_union, i, Min(GIDX_GET_MIN(*b_union,i),GIDX_GET_MIN(b_new,i)));
		/* Adjust maximums */
		GIDX_SET_MAX(*b_union, i, Max(GIDX_GET_MAX(*b_union,i),GIDX_GET_MAX(b_new,i)));
	}

	POSTGIS_DEBUGF(5, "merge complete (%s)", gidx_to_string(*b_union));
	return;
}
Example #3
0
/*
** GIDX expansion, make d units bigger in all dimensions.
*/
void gidx_expand(GIDX *a, float d)
{
	int i;

	POSTGIS_DEBUG(5, "entered function");

	if ( a == NULL ) return;

	for (i = 0; i < GIDX_NDIMS(a); i++)
	{
		GIDX_SET_MIN(a, i, GIDX_GET_MIN(a, i) - d);
		GIDX_SET_MAX(a, i, GIDX_GET_MAX(a, i) + d);
	}
}
/* Ensure all minimums are below maximums. */
static inline void gidx_validate(GIDX *b)
{
	int i;
	Assert(b);
	POSTGIS_DEBUGF(5,"validating gidx (%s)", gidx_to_string(b));
	for ( i = 0; i < GIDX_NDIMS(b); i++ )
	{
		if ( GIDX_GET_MIN(b,i) > GIDX_GET_MAX(b,i) )
		{
			float tmp;
			tmp = GIDX_GET_MIN(b,i);
			GIDX_SET_MIN(b,i,GIDX_GET_MAX(b,i));
			GIDX_SET_MAX(b,i,tmp);
		}
	}
	return;
}
/* Convert a double-based GBOX into a float-based GIDX,
   ensuring the float box is larger than the double box */
static int gidx_from_gbox_p(GBOX box, GIDX *a)
{
	int ndims;

	ndims = (FLAGS_GET_GEODETIC(box.flags) ? 3 : FLAGS_NDIMS(box.flags));
	SET_VARSIZE(a, VARHDRSZ + ndims * 2 * sizeof(float));

	GIDX_SET_MIN(a,0,nextDown_f(box.xmin));
	GIDX_SET_MAX(a,0,nextUp_f(box.xmax));
	GIDX_SET_MIN(a,1,nextDown_f(box.ymin));
	GIDX_SET_MAX(a,1,nextUp_f(box.ymax));

	/* Geodetic indexes are always 3d, geocentric x/y/z */
	if ( FLAGS_GET_GEODETIC(box.flags) )
	{
		GIDX_SET_MIN(a,2,nextDown_f(box.zmin));
		GIDX_SET_MAX(a,2,nextUp_f(box.zmax));
	}
	else
	{
		/* Cartesian with Z implies Z is third dimension */
		if ( FLAGS_GET_Z(box.flags) )
		{
			GIDX_SET_MIN(a,2,nextDown_f(box.zmin));
			GIDX_SET_MAX(a,2,nextUp_f(box.zmax));
			if ( FLAGS_GET_M(box.flags) )
			{
				GIDX_SET_MIN(a,3,nextDown_f(box.mmin));
				GIDX_SET_MAX(a,3,nextUp_f(box.mmax));
			}
		}
		/* Unless there's no Z, in which case M is third dimension */
		else if ( FLAGS_GET_M(box.flags) )
		{
			GIDX_SET_MIN(a,2,nextDown_f(box.mmin));
			GIDX_SET_MAX(a,2,nextUp_f(box.mmax));
		}
	}

	POSTGIS_DEBUGF(5, "converted %s to %s", gbox_to_string(&box), gidx_to_string(a));

	return G_SUCCESS;
}
Example #6
0
/* Convert a double-based GBOX into a float-based GIDX,
   ensuring the float box is larger than the double box */
static int gidx_from_gbox_p(GBOX box, GIDX *a)
{
	int ndims;

	ndims = FLAGS_NDIMS_GIDX(box.flags);
	SET_VARSIZE(a, VARHDRSZ + ndims * 2 * sizeof(float));

	GIDX_SET_MIN(a,0,next_float_down(box.xmin));
	GIDX_SET_MAX(a,0,next_float_up(box.xmax));
	GIDX_SET_MIN(a,1,next_float_down(box.ymin));
	GIDX_SET_MAX(a,1,next_float_up(box.ymax));

	/* Geodetic indexes are always 3d, geocentric x/y/z */
	if ( FLAGS_GET_GEODETIC(box.flags) )
	{
		GIDX_SET_MIN(a,2,next_float_down(box.zmin));
		GIDX_SET_MAX(a,2,next_float_up(box.zmax));
	}
	else
	{
		/* Cartesian with Z implies Z is third dimension */
		if ( FLAGS_GET_Z(box.flags) )
		{
			GIDX_SET_MIN(a,2,next_float_down(box.zmin));
			GIDX_SET_MAX(a,2,next_float_up(box.zmax));
		}
		/* M is always fourth dimension, we pad if needed */
		if ( FLAGS_GET_M(box.flags) )
		{
			if ( ! FLAGS_GET_Z(box.flags) )
			{
				GIDX_SET_MIN(a,2,-1*FLT_MAX);
				GIDX_SET_MAX(a,2,FLT_MAX);
			}
			GIDX_SET_MIN(a,3,next_float_down(box.mmin));
			GIDX_SET_MAX(a,3,next_float_up(box.mmax));
		}
	}

	POSTGIS_DEBUGF(5, "converted %s to %s", gbox_to_string(&box), gidx_to_string(a));

	return LW_SUCCESS;
}