/* * Construct a new LWCIRCSTRING. points will *NOT* be copied * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0) */ LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points) { LWCIRCSTRING *result; /* * The first arc requires three points. Each additional * arc requires two more points. Thus the minimum point count * is three, and the count must be odd. */ if (points->npoints % 2 != 1 || points->npoints < 3) { lwnotice("lwcircstring_construct: invalid point count %d", points->npoints); } result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING)); result->type = CIRCSTRINGTYPE; result->flags = points->flags; FLAGS_SET_BBOX(result->flags, bbox?1:0); result->srid = srid; result->points = points; result->bbox = bbox; return result; }
void lwgeom_add_bbox_deep(LWGEOM *lwgeom, GBOX *gbox) { if ( lwgeom_is_empty(lwgeom) ) return; FLAGS_SET_BBOX(lwgeom->flags, 1); if ( ! ( gbox || lwgeom->bbox ) ) { lwgeom->bbox = gbox_new(lwgeom->flags); lwgeom_calculate_gbox(lwgeom, lwgeom->bbox); } else if ( gbox && ! lwgeom->bbox ) { lwgeom->bbox = gbox_clone(gbox); } if ( lwgeom_is_collection(lwgeom) ) { int i; LWCOLLECTION *lwcol = (LWCOLLECTION*)lwgeom; for ( i = 0; i < lwcol->ngeoms; i++ ) { lwgeom_add_bbox_deep(lwcol->geoms[i], lwgeom->bbox); } } }
void lwgeom_drop_bbox(LWGEOM *lwgeom) { if ( lwgeom->bbox ) lwfree(lwgeom->bbox); lwgeom->bbox = NULL; FLAGS_SET_BBOX(lwgeom->flags, 0); }
/** * Remove the bounding box from a #GSERIALIZED. Returns a freshly * allocated #GSERIALIZED every time. */ GSERIALIZED* gserialized_drop_gidx(GSERIALIZED *g) { int g_ndims = FLAGS_NDIMS_BOX(g->flags); size_t box_size = 2 * g_ndims * sizeof(float); size_t g_out_size = VARSIZE(g) - box_size; GSERIALIZED *g_out = palloc(g_out_size); /* Copy the contents while omitting the box */ if ( FLAGS_GET_BBOX(g->flags) ) { uint8_t *outptr = (uint8_t*)g_out; uint8_t *inptr = (uint8_t*)g; /* Copy the header (size+type) of g into place */ memcpy(outptr, inptr, 8); outptr += 8; inptr += 8 + box_size; /* Copy parts after the box into place */ memcpy(outptr, inptr, g_out_size - 8); FLAGS_SET_BBOX(g_out->flags, 0); SET_VARSIZE(g_out, g_out_size); } /* No box? Nothing to do but copy and return. */ else { memcpy(g_out, g, g_out_size); } return g_out; }
/** * Ensure there's a box in the LWGEOM. * If the box is already there just return, * else compute it. */ void lwgeom_add_bbox(LWGEOM *lwgeom) { /* an empty LWGEOM has no bbox */ if ( lwgeom_is_empty(lwgeom) ) return; if ( lwgeom->bbox ) return; FLAGS_SET_BBOX(lwgeom->flags, 1); lwgeom->bbox = gbox_new(lwgeom->flags); lwgeom_calculate_gbox(lwgeom, lwgeom->bbox); }
static LWCOLLECTION* lwcollection_from_gserialized_buffer(uint8_t *data_ptr, uint8_t g_flags, size_t *g_size) { uint32_t type; uint8_t *start_ptr = data_ptr; LWCOLLECTION *collection; uint32_t ngeoms = 0; int i = 0; assert(data_ptr); type = lw_get_uint32_t(data_ptr); data_ptr += 4; /* Skip past the type. */ collection = (LWCOLLECTION*)lwalloc(sizeof(LWCOLLECTION)); collection->srid = SRID_UNKNOWN; /* Default */ collection->bbox = NULL; collection->type = type; collection->flags = g_flags; ngeoms = lw_get_uint32_t(data_ptr); collection->ngeoms = ngeoms; /* Zero => empty geometry */ data_ptr += 4; /* Skip past the ngeoms. */ if ( ngeoms > 0 ) collection->geoms = lwalloc(sizeof(LWGEOM*) * ngeoms); else collection->geoms = NULL; /* Sub-geometries are never de-serialized with boxes (#1254) */ FLAGS_SET_BBOX(g_flags, 0); for ( i = 0; i < ngeoms; i++ ) { uint32_t subtype = lw_get_uint32_t(data_ptr); size_t subsize = 0; if ( ! lwcollection_allows_subtype(type, subtype) ) { lwerror("Invalid subtype (%s) for collection type (%s)", lwtype_name(subtype), lwtype_name(type)); lwfree(collection); return NULL; } collection->geoms[i] = lwgeom_from_gserialized_buffer(data_ptr, g_flags, &subsize); data_ptr += subsize; } if ( g_size ) *g_size = data_ptr - start_ptr; return collection; }
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms) { LWCOLLECTION *ret; int hasz, hasm; #ifdef CHECK_LWGEOM_ZM char zm; uint32_t i; #endif LWDEBUGF(2, "lwcollection_construct called with %d, %d, %p, %d, %p.", type, srid, bbox, ngeoms, geoms); if( ! lwtype_is_collection(type) ) lwerror("Non-collection type specified in collection constructor!"); hasz = 0; hasm = 0; if ( ngeoms > 0 ) { hasz = FLAGS_GET_Z(geoms[0]->flags); hasm = FLAGS_GET_M(geoms[0]->flags); #ifdef CHECK_LWGEOM_ZM zm = FLAGS_GET_ZM(geoms[0]->flags); LWDEBUGF(3, "lwcollection_construct type[0]=%d", geoms[0]->type); for (i=1; i<ngeoms; i++) { LWDEBUGF(3, "lwcollection_construct type=[%d]=%d", i, geoms[i]->type); if ( zm != FLAGS_GET_ZM(geoms[i]->flags) ) lwerror("lwcollection_construct: mixed dimension geometries: %d/%d", zm, FLAGS_GET_ZM(geoms[i]->flags)); } #endif } ret = lwalloc(sizeof(LWCOLLECTION)); ret->type = type; ret->flags = gflags(hasz,hasm,0); FLAGS_SET_BBOX(ret->flags, bbox?1:0); ret->srid = srid; ret->ngeoms = ngeoms; ret->maxgeoms = ngeoms; ret->geoms = geoms; ret->bbox = bbox; return ret; }
/* construct a new LWTRIANGLE. * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0) */ LWTRIANGLE* lwtriangle_construct(int srid, GBOX *bbox, POINTARRAY *points) { LWTRIANGLE *result; result = (LWTRIANGLE*) lwalloc(sizeof(LWTRIANGLE)); result->type = TRIANGLETYPE; result->flags = points->flags; FLAGS_SET_BBOX(result->flags, bbox?1:0); result->srid = srid; result->points = points; result->bbox = bbox; return result; }
/* ** 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; }
/* * Construct a new point. point will not be copied * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0) */ LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point) { LWPOINT *result; uint8_t flags = 0; if (point == NULL) return NULL; /* error */ result = lwalloc(sizeof(LWPOINT)); result->type = POINTTYPE; FLAGS_SET_Z(flags, FLAGS_GET_Z(point->flags)); FLAGS_SET_M(flags, FLAGS_GET_M(point->flags)); FLAGS_SET_BBOX(flags, bbox?1:0); result->flags = flags; result->srid = srid; result->point = point; result->bbox = bbox; return result; }
/* construct a new LWPOLY. arrays (points/points per ring) will NOT be copied * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0) */ LWPOLY* lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points) { LWPOLY *result; int hasz, hasm; #ifdef CHECK_POLY_RINGS_ZM char zm; uint32_t i; #endif if ( nrings < 1 ) lwerror("lwpoly_construct: need at least 1 ring"); hasz = FLAGS_GET_Z(points[0]->flags); hasm = FLAGS_GET_M(points[0]->flags); #ifdef CHECK_POLY_RINGS_ZM zm = FLAGS_GET_ZM(points[0]->flags); for (i=1; i<nrings; i++) { if ( zm != FLAGS_GET_ZM(points[i]->flags) ) lwerror("lwpoly_construct: mixed dimensioned rings"); } #endif result = (LWPOLY*) lwalloc(sizeof(LWPOLY)); result->type = POLYGONTYPE; result->flags = gflags(hasz, hasm, 0); FLAGS_SET_BBOX(result->flags, bbox?1:0); result->srid = srid; result->nrings = nrings; result->maxrings = nrings; result->rings = points; result->bbox = bbox; return result; }
GSERIALIZED* gserialized_from_lwgeom(LWGEOM *geom, int is_geodetic, size_t *size) { size_t expected_size = 0; size_t return_size = 0; uint8_t *serialized = NULL; uint8_t *ptr = NULL; GSERIALIZED *g = NULL; assert(geom); /* ** See if we need a bounding box, add one if we don't have one. */ if ( (! geom->bbox) && lwgeom_needs_bbox(geom) && (!lwgeom_is_empty(geom)) ) { lwgeom_add_bbox(geom); } /* ** Harmonize the flags to the state of the lwgeom */ if ( geom->bbox ) FLAGS_SET_BBOX(geom->flags, 1); /* Set up the uint8_t buffer into which we are going to write the serialized geometry. */ expected_size = gserialized_from_lwgeom_size(geom); serialized = lwalloc(expected_size); ptr = serialized; /* Move past size, srid and flags. */ ptr += 8; /* Write in the serialized form of the gbox, if necessary. */ if ( geom->bbox ) ptr += gserialized_from_gbox(geom->bbox, ptr); /* Write in the serialized form of the geometry. */ ptr += gserialized_from_lwgeom_any(geom, ptr); /* Calculate size as returned by data processing functions. */ return_size = ptr - serialized; if ( expected_size != return_size ) /* Uh oh! */ { lwerror("Return size (%d) not equal to expected size (%d)!", return_size, expected_size); return NULL; } if ( size ) /* Return the output size to the caller if necessary. */ *size = return_size; g = (GSERIALIZED*)serialized; /* ** We are aping PgSQL code here, PostGIS code should use ** VARSIZE to set this for real. */ g->size = return_size << 2; /* Set the SRID! */ gserialized_set_srid(g, geom->srid); g->flags = geom->flags; return g; }