int gbox_overlaps(const GBOX *g1, const GBOX *g2) { /* Make sure our boxes are consistent */ if ( FLAGS_GET_GEODETIC(g1->flags) != FLAGS_GET_GEODETIC(g2->flags) ) lwerror("gbox_overlaps: cannot compare geodetic and non-geodetic boxes"); /* Check X/Y first */ if ( g1->xmax < g2->xmin || g1->ymax < g2->ymin || g1->xmin > g2->xmax || g1->ymin > g2->ymax ) return LW_FALSE; /* If both geodetic or both have Z, check Z */ if ( (FLAGS_GET_Z(g1->flags) && FLAGS_GET_Z(g2->flags)) || (FLAGS_GET_GEODETIC(g1->flags) && FLAGS_GET_GEODETIC(g2->flags)) ) { if ( g1->zmax < g2->zmin || g1->zmin > g2->zmax ) return LW_FALSE; } /* If both have M, check M */ if ( FLAGS_GET_M(g1->flags) && FLAGS_GET_M(g2->flags) ) { if ( g1->mmax < g2->mmin || g1->mmin > g2->mmax ) return LW_FALSE; } return LW_TRUE; }
int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2) { /* Make sure our boxes are consistent */ if ( FLAGS_GET_GEODETIC(g1->flags) != FLAGS_GET_GEODETIC(g2->flags) ) lwerror("gbox_overlaps: cannot compare geodetic and non-geodetic boxes"); /* Check X/Y first */ if ( g1->xmax < g2->xmin || g1->ymax < g2->ymin || g1->xmin > g2->xmax || g1->ymin > g2->ymax ) return LW_FALSE; return LW_TRUE; }
int gbox_is_valid(const GBOX *gbox) { /* X */ if ( ! isfinite(gbox->xmin) || isnan(gbox->xmin) || ! isfinite(gbox->xmax) || isnan(gbox->xmax) ) return LW_FALSE; /* Y */ if ( ! isfinite(gbox->ymin) || isnan(gbox->ymin) || ! isfinite(gbox->ymax) || isnan(gbox->ymax) ) return LW_FALSE; /* Z */ if ( FLAGS_GET_GEODETIC(gbox->flags) || FLAGS_GET_Z(gbox->flags) ) { if ( ! isfinite(gbox->zmin) || isnan(gbox->zmin) || ! isfinite(gbox->zmax) || isnan(gbox->zmax) ) return LW_FALSE; } /* M */ if ( FLAGS_GET_M(gbox->flags) ) { if ( ! isfinite(gbox->mmin) || isnan(gbox->mmin) || ! isfinite(gbox->mmax) || isnan(gbox->mmax) ) return LW_FALSE; } return LW_TRUE; }
int gbox_merge(const GBOX *new_box, GBOX *merge_box) { assert(merge_box); if ( FLAGS_GET_ZM(merge_box->flags) != FLAGS_GET_ZM(new_box->flags) ) return LW_FAILURE; if ( new_box->xmin < merge_box->xmin) merge_box->xmin = new_box->xmin; if ( new_box->ymin < merge_box->ymin) merge_box->ymin = new_box->ymin; if ( new_box->xmax > merge_box->xmax) merge_box->xmax = new_box->xmax; if ( new_box->ymax > merge_box->ymax) merge_box->ymax = new_box->ymax; if ( FLAGS_GET_Z(merge_box->flags) || FLAGS_GET_GEODETIC(merge_box->flags) ) { if ( new_box->zmin < merge_box->zmin) merge_box->zmin = new_box->zmin; if ( new_box->zmax > merge_box->zmax) merge_box->zmax = new_box->zmax; } if ( FLAGS_GET_M(merge_box->flags) ) { if ( new_box->mmin < merge_box->mmin) merge_box->mmin = new_box->mmin; if ( new_box->mmax > merge_box->mmax) merge_box->mmax = new_box->mmax; } return LW_SUCCESS; }
char* gbox_to_string(const GBOX *gbox) { static int sz = 128; char *str = NULL; if ( ! gbox ) return strdup("NULL POINTER"); str = (char*)lwalloc(sz); if ( FLAGS_GET_GEODETIC(gbox->flags) ) { snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->zmin, gbox->xmax, gbox->ymax, gbox->zmax); return str; } if ( FLAGS_GET_Z(gbox->flags) && FLAGS_GET_M(gbox->flags) ) { snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->zmin, gbox->mmin, gbox->xmax, gbox->ymax, gbox->zmax, gbox->mmax); return str; } if ( FLAGS_GET_Z(gbox->flags) ) { snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->zmin, gbox->xmax, gbox->ymax, gbox->zmax); return str; } if ( FLAGS_GET_M(gbox->flags) ) { snprintf(str, sz, "GBOX((%.8g,%.8g,%.8g),(%.8g,%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->mmin, gbox->xmax, gbox->ymax, gbox->mmax); return str; } snprintf(str, sz, "GBOX((%.8g,%.8g),(%.8g,%.8g))", gbox->xmin, gbox->ymin, gbox->xmax, gbox->ymax); return str; }
/* ** Peak into a geography to find the bounding box. If the ** box is there, copy it out and return it. If not, calculate the box from the ** full geography and return the box based on that. If no box is available, ** return G_FAILURE, otherwise G_SUCCESS. */ int geography_gidx(GSERIALIZED *g, GIDX *gidx) { int result = G_SUCCESS; POSTGIS_DEBUG(4, "entered function"); POSTGIS_DEBUGF(4, "got flags %d", g->flags); if ( FLAGS_GET_BBOX(g->flags) && FLAGS_GET_GEODETIC(g->flags) ) { const size_t size = 2 * 3 * sizeof(float); POSTGIS_DEBUG(4, "copying box out of serialization"); memcpy(gidx->c, g->data, size); SET_VARSIZE(gidx, VARHDRSZ + size); } else { GBOX gbox; POSTGIS_DEBUG(4, "calculating new box from scratch"); if ( gserialized_calculate_gbox_geocentric_p(g, &gbox) == G_FAILURE ) { POSTGIS_DEBUG(4, "calculated null bbox, returning null"); return G_FAILURE; } result = gidx_from_gbox_p(gbox, gidx); } if ( result == G_SUCCESS ) { POSTGIS_DEBUGF(4, "got gidx %s", gidx_to_string(gidx)); } return result; }
size_t gbox_serialized_size(uint8_t flags) { if ( FLAGS_GET_GEODETIC(flags) ) return 6 * sizeof(float); else return 2 * FLAGS_NDIMS(flags) * sizeof(float); }
/** * Calculate the gbox for this goemetry, a cartesian box or * geodetic box, depending on how it is flagged. */ int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox) { gbox->flags = lwgeom->flags; if( FLAGS_GET_GEODETIC(lwgeom->flags) ) return lwgeom_calculate_gbox_geodetic(lwgeom, gbox); else return lwgeom_calculate_gbox_cartesian(lwgeom, gbox); }
size_t gbox_serialized_size(uchar flags) { if ( ! FLAGS_GET_BBOX(flags) ) return 0; if ( FLAGS_GET_GEODETIC(flags) ) return 6 * sizeof(float); else return 2 * FLAGS_NDIMS(flags) * sizeof(float); }
GIDX* gidx_from_gbox(GBOX box) { int ndims; GIDX *a; ndims = (FLAGS_GET_GEODETIC(box.flags) ? 3 : FLAGS_NDIMS(box.flags)); a = gidx_new(ndims); gidx_from_gbox_p(box, a); return a; }
/* 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; }
int gbox_from_gserialized(const GSERIALIZED *g, GBOX *gbox) { /* Null input! */ if ( ! g ) return G_FAILURE; /* Initialize the flags on the box */ gbox->flags = g->flags; if ( FLAGS_GET_BBOX(g->flags) ) { int i = 0; float *fbox = (float*)(g->data); gbox->xmin = fbox[i]; i++; gbox->xmax = fbox[i]; i++; gbox->ymin = fbox[i]; i++; gbox->ymax = fbox[i]; i++; if ( FLAGS_GET_GEODETIC(g->flags) ) { gbox->zmin = fbox[i]; i++; gbox->zmax = fbox[i]; i++; return G_SUCCESS; } if ( FLAGS_GET_Z(g->flags) ) { gbox->zmin = fbox[i]; i++; gbox->zmax = fbox[i]; i++; } if ( FLAGS_GET_M(g->flags) ) { gbox->mmin = fbox[i]; i++; gbox->mmax = fbox[i]; i++; } return G_SUCCESS; } LWDEBUG(4, "calculating new box from scratch"); if ( gserialized_calculate_gbox_geocentric_p(g, gbox) == G_FAILURE ) { LWDEBUG(4, "calculated null bbox, returning failure"); return G_FAILURE; } return G_SUCCESS; }
int gbox_overlaps(const GBOX *g1, const GBOX *g2) { /* Make sure our boxes are consistent */ if ( FLAGS_GET_GEODETIC(g1->flags) != FLAGS_GET_GEODETIC(g2->flags) ) lwerror("gbox_overlaps: cannot compare geodetic and non-geodetic boxes"); /* Check X/Y first */ if ( g1->xmax < g2->xmin || g1->ymax < g2->ymin || g1->xmin > g2->xmax || g1->ymin > g2->ymax ) return LW_FALSE; /* Deal with the geodetic case special: we only compare the geodetic boxes (x/y/z) */ /* Never the M dimension */ if ( FLAGS_GET_GEODETIC(g1->flags) && FLAGS_GET_GEODETIC(g2->flags) ) { if ( g1->zmax < g2->zmin || g1->zmin > g2->zmax ) return LW_FALSE; else return LW_TRUE; } /* If both geodetic or both have Z, check Z */ if ( FLAGS_GET_Z(g1->flags) && FLAGS_GET_Z(g2->flags) ) { if ( g1->zmax < g2->zmin || g1->zmin > g2->zmax ) return LW_FALSE; } /* If both have M, check M */ if ( FLAGS_GET_M(g1->flags) && FLAGS_GET_M(g2->flags) ) { if ( g1->mmax < g2->mmin || g1->mmin > g2->mmax ) return LW_FALSE; } return LW_TRUE; }
/* ** Make a copy of a GSERIALIZED, with a new bounding box value embedded. */ GSERIALIZED* gidx_insert_into_gserialized(GSERIALIZED *g, GIDX *gidx) { int g_ndims = (FLAGS_GET_GEODETIC(g->flags) ? 3 : FLAGS_NDIMS(g->flags)); int box_ndims = GIDX_NDIMS(gidx); GSERIALIZED *g_out = NULL; size_t box_size = 2 * g_ndims * sizeof(float); /* The dimensionality of the inputs has to match or we are SOL. */ if ( g_ndims != box_ndims ) { return NULL; } /* Serialized already has room for a box. We just need to copy it and write the new values into place. */ if ( FLAGS_GET_BBOX(g->flags) ) { g_out = palloc(VARSIZE(g)); memcpy(g_out, g, VARSIZE(g)); } /* Serialized has no box. We need to allocate enough space for the old data plus the box, and leave a gap in the memory segment to write the new values into. */ else { size_t varsize_new = VARSIZE(g) + box_size; uchar *ptr; g_out = palloc(varsize_new); /* Copy the head of g into place */ memcpy(g_out, g, 8); /* Copy the body of g into place after leaving space for the box */ ptr = g_out->data; ptr += box_size; memcpy(ptr, g->data, VARSIZE(g) - 8); FLAGS_SET_BBOX(g_out->flags, 1); SET_VARSIZE(g_out, varsize_new); } /* Now write the gidx values into the memory segement */ memcpy(g_out->data, gidx->c, box_size); return g_out; }
/* 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; }
/* ** Peak into a geography (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 geography and return the box based on that. If no box is available, ** return G_FAILURE, otherwise G_SUCCESS. */ int geography_datum_gidx(Datum geography_datum, GIDX *gidx) { GSERIALIZED *gpart; int result = G_SUCCESS; POSTGIS_DEBUG(4, "entered function"); /* ** The most info we need is the 8 bytes of serialized header plus the 24 bytes ** of floats necessary to hold the 6 floats of the geocentric index ** bounding box, so 32 bytes. */ gpart = (GSERIALIZED*)PG_DETOAST_DATUM_SLICE(geography_datum, 0, 32); POSTGIS_DEBUGF(4, "got flags %d", gpart->flags); if ( FLAGS_GET_BBOX(gpart->flags) && FLAGS_GET_GEODETIC(gpart->flags) ) { const size_t size = 2 * 3 * sizeof(float); POSTGIS_DEBUG(4, "copying box out of serialization"); memcpy(gidx->c, gpart->data, size); SET_VARSIZE(gidx, VARHDRSZ + size); } else { GSERIALIZED *g = (GSERIALIZED*)PG_DETOAST_DATUM(geography_datum); GBOX gbox; POSTGIS_DEBUG(4, "calculating new box from scratch"); if ( gserialized_calculate_gbox_geocentric_p(g, &gbox) == G_FAILURE ) { POSTGIS_DEBUG(4, "calculated null bbox, returning null"); return G_FAILURE; } result = gidx_from_gbox_p(gbox, gidx); } if ( result == G_SUCCESS ) { POSTGIS_DEBUGF(4, "got gidx %s", gidx_to_string(gidx)); } return result; }
int gserialized_read_gbox_p(const GSERIALIZED *g, GBOX *gbox) { /* Null input! */ if ( ! ( g && gbox ) ) return LW_FAILURE; /* Initialize the flags on the box */ gbox->flags = g->flags; /* Has pre-calculated box */ if ( FLAGS_GET_BBOX(g->flags) ) { int i = 0; float *fbox = (float*)(g->data); gbox->xmin = fbox[i++]; gbox->xmax = fbox[i++]; gbox->ymin = fbox[i++]; gbox->ymax = fbox[i++]; /* Geodetic? Read next dimension (geocentric Z) and return */ if ( FLAGS_GET_GEODETIC(g->flags) ) { gbox->zmin = fbox[i++]; gbox->zmax = fbox[i++]; return LW_SUCCESS; } /* Cartesian? Read extra dimensions (if there) and return */ if ( FLAGS_GET_Z(g->flags) ) { gbox->zmin = fbox[i++]; gbox->zmax = fbox[i++]; } if ( FLAGS_GET_M(g->flags) ) { gbox->mmin = fbox[i++]; gbox->mmax = fbox[i++]; } return LW_SUCCESS; } return LW_FAILURE; }
LWGEOM* lwgeom_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size) { uint32_t type; assert(data_ptr); type = lw_get_uint32_t(data_ptr); LWDEBUGF(2, "Got type %d (%s), hasz=%d hasm=%d geodetic=%d hasbox=%d", type, lwtype_name(type), FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), FLAGS_GET_GEODETIC(g_flags), FLAGS_GET_BBOX(g_flags)); switch (type) { case POINTTYPE: return (LWGEOM *)lwpoint_from_gserialized_buffer(data_ptr, g_flags, g_size); case LINETYPE: return (LWGEOM *)lwline_from_gserialized_buffer(data_ptr, g_flags, g_size); case CIRCSTRINGTYPE: return (LWGEOM *)lwcircstring_from_gserialized_buffer(data_ptr, g_flags, g_size); case POLYGONTYPE: return (LWGEOM *)lwpoly_from_gserialized_buffer(data_ptr, g_flags, g_size); case TRIANGLETYPE: return (LWGEOM *)lwtriangle_from_gserialized_buffer(data_ptr, g_flags, g_size); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: return (LWGEOM *)lwcollection_from_gserialized_buffer(data_ptr, g_flags, g_size); default: lwerror("Unknown geometry type: %d - %s", type, lwtype_name(type)); return NULL; } }
void gbox_duplicate(const GBOX *original, GBOX *duplicate) { assert(duplicate); if ( original->flags != duplicate->flags ) lwerror("gbox_duplicate: geometries have inconsistent dimensionality"); duplicate->xmin = original->xmin; duplicate->ymin = original->ymin; duplicate->xmax = original->xmax; duplicate->ymax = original->ymax; if ( FLAGS_GET_GEODETIC(original->flags) || FLAGS_GET_Z(original->flags) ) { duplicate->zmin = original->zmin; duplicate->zmax = original->zmax; } if ( FLAGS_GET_M(original->flags) ) { duplicate->mmin = original->mmin; duplicate->mmax = original->mmax; } return; }
static size_t gserialized_from_gbox(const GBOX *gbox, uint8_t *buf) { uint8_t *loc = buf; float f; size_t return_size; assert(buf); f = next_float_down(gbox->xmin); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); f = next_float_up(gbox->xmax); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); f = next_float_down(gbox->ymin); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); f = next_float_up(gbox->ymax); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); if ( FLAGS_GET_GEODETIC(gbox->flags) ) { f = next_float_down(gbox->zmin); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); f = next_float_up(gbox->zmax); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); return_size = (size_t)(loc - buf); LWDEBUGF(4, "returning size %d", return_size); return return_size; } if ( FLAGS_GET_Z(gbox->flags) ) { f = next_float_down(gbox->zmin); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); f = next_float_up(gbox->zmax); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); } if ( FLAGS_GET_M(gbox->flags) ) { f = next_float_down(gbox->mmin); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); f = next_float_up(gbox->mmax); memcpy(loc, &f, sizeof(float)); loc += sizeof(float); } return_size = (size_t)(loc - buf); LWDEBUGF(4, "returning size %d", return_size); return return_size; }
/* * Populate a bounding box *without* allocating an LWGEOM. Useful * for some performance purposes. */ static int gserialized_peek_gbox_p(const GSERIALIZED *g, GBOX *gbox) { uint32_t type = gserialized_get_type(g); /* Peeking doesn't help if you already have a box or are geodetic */ if ( FLAGS_GET_GEODETIC(g->flags) || FLAGS_GET_BBOX(g->flags) ) { return LW_FAILURE; } /* Boxes of points are easy peasy */ if ( type == POINTTYPE ) { int i = 1; /* Start past <pointtype><padding> */ double *dptr = (double*)(g->data); /* Read the empty flag */ int *iptr = (int*)(g->data); int isempty = (iptr[1] == 0); /* EMPTY point has no box */ if ( isempty ) return LW_FAILURE; gbox->xmin = gbox->xmax = dptr[i++]; gbox->ymin = gbox->ymax = dptr[i++]; if ( FLAGS_GET_Z(g->flags) ) { gbox->zmin = gbox->zmax = dptr[i++]; } if ( FLAGS_GET_M(g->flags) ) { gbox->mmin = gbox->mmax = dptr[i++]; } gbox_float_round(gbox); return LW_SUCCESS; } /* We can calculate the box of a two-point cartesian line trivially */ else if ( type == LINETYPE ) { int ndims = FLAGS_NDIMS(g->flags); int i = 0; /* Start at <linetype><npoints> */ double *dptr = (double*)(g->data); int *iptr = (int*)(g->data); int npoints = iptr[1]; /* Read the npoints */ /* This only works with 2-point lines */ if ( npoints != 2 ) return LW_FAILURE; /* Advance to X */ /* Past <linetype><npoints> */ i++; gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]); /* Advance to Y */ i++; gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]); if ( FLAGS_GET_Z(g->flags) ) { /* Advance to Z */ i++; gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]); } if ( FLAGS_GET_M(g->flags) ) { /* Advance to M */ i++; gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]); } gbox_float_round(gbox); return LW_SUCCESS; } /* We can also do single-entry multi-points */ else if ( type == MULTIPOINTTYPE ) { int i = 0; /* Start at <multipointtype><ngeoms> */ double *dptr = (double*)(g->data); int *iptr = (int*)(g->data); int ngeoms = iptr[1]; /* Read the ngeoms */ /* This only works with single-entry multipoints */ if ( ngeoms != 1 ) return LW_FAILURE; /* Move forward two doubles (four ints) */ /* Past <multipointtype><ngeoms> */ /* Past <pointtype><emtpyflat> */ i += 2; /* Read the doubles from the one point */ gbox->xmin = gbox->xmax = dptr[i++]; gbox->ymin = gbox->ymax = dptr[i++]; if ( FLAGS_GET_Z(g->flags) ) { gbox->zmin = gbox->zmax = dptr[i++]; } if ( FLAGS_GET_M(g->flags) ) { gbox->mmin = gbox->mmax = dptr[i++]; } gbox_float_round(gbox); return LW_SUCCESS; } /* And we can do single-entry multi-lines with two vertices (!!!) */ else if ( type == MULTILINETYPE ) { int ndims = FLAGS_NDIMS(g->flags); int i = 0; /* Start at <multilinetype><ngeoms> */ double *dptr = (double*)(g->data); int *iptr = (int*)(g->data); int ngeoms = iptr[1]; /* Read the ngeoms */ int npoints; /* This only works with 1-line multilines */ if ( ngeoms != 1 ) return LW_FAILURE; /* Npoints is at <multilinetype><ngeoms><linetype><npoints> */ npoints = iptr[3]; if ( npoints != 2 ) return LW_FAILURE; /* Advance to X */ /* Move forward two doubles (four ints) */ /* Past <multilinetype><ngeoms> */ /* Past <linetype><npoints> */ i += 2; gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]); /* Advance to Y */ i++; gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]); if ( FLAGS_GET_Z(g->flags) ) { /* Advance to Z */ i++; gbox->zmin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->zmax = FP_MAX(dptr[i], dptr[i+ndims]); } if ( FLAGS_GET_M(g->flags) ) { /* Advance to M */ i++; gbox->mmin = FP_MIN(dptr[i], dptr[i+ndims]); gbox->mmax = FP_MAX(dptr[i], dptr[i+ndims]); } gbox_float_round(gbox); return LW_SUCCESS; } return LW_FAILURE; }
int gserialized_is_geodetic(const GSERIALIZED *gser) { return FLAGS_GET_GEODETIC(gser->flags); }