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; }
static size_t gserialized_from_lwcollection(const LWCOLLECTION *coll, uint8_t *buf) { size_t subsize = 0; uint8_t *loc; int i; int type; assert(coll); assert(buf); type = coll->type; loc = buf; /* Write in the type. */ memcpy(loc, &type, sizeof(uint32_t)); loc += sizeof(uint32_t); /* Write in the number of subgeoms. */ memcpy(loc, &coll->ngeoms, sizeof(uint32_t)); loc += sizeof(uint32_t); /* Serialize subgeoms. */ for ( i=0; i<coll->ngeoms; i++ ) { if (FLAGS_GET_ZM(coll->flags) != FLAGS_GET_ZM(coll->geoms[i]->flags)) lwerror("Dimensions mismatch in lwcollection"); subsize = gserialized_from_lwgeom_any(coll->geoms[i], loc); loc += subsize; } return (size_t)(loc - buf); }
/** * @brief Merge two given POINTARRAY and returns a pointer * on the new aggregate one. * Warning: this function free the two inputs POINTARRAY * @return #POINTARRAY is newly allocated */ POINTARRAY * ptarray_merge(POINTARRAY *pa1, POINTARRAY *pa2) { POINTARRAY *pa; size_t ptsize = ptarray_point_size(pa1); if (FLAGS_GET_ZM(pa1->flags) != FLAGS_GET_ZM(pa2->flags)) lwerror("ptarray_cat: Mixed dimension"); pa = ptarray_construct( FLAGS_GET_Z(pa1->flags), FLAGS_GET_M(pa1->flags), pa1->npoints + pa2->npoints); memcpy( getPoint_internal(pa, 0), getPoint_internal(pa1, 0), ptsize*(pa1->npoints)); memcpy( getPoint_internal(pa, pa1->npoints), getPoint_internal(pa2, 0), ptsize*(pa2->npoints)); lwfree(pa1); lwfree(pa2); return pa; }
static size_t gserialized_from_lwcircstring(const LWCIRCSTRING *curve, uint8_t *buf) { uint8_t *loc; int ptsize; size_t size; int type = CIRCSTRINGTYPE; assert(curve); assert(buf); if (FLAGS_GET_ZM(curve->flags) != FLAGS_GET_ZM(curve->points->flags)) lwerror("Dimensions mismatch in lwcircstring"); ptsize = ptarray_point_size(curve->points); loc = buf; /* Write in the type. */ memcpy(loc, &type, sizeof(uint32_t)); loc += sizeof(uint32_t); /* Write in the npoints. */ memcpy(loc, &curve->points->npoints, sizeof(uint32_t)); loc += sizeof(uint32_t); /* Copy in the ordinates. */ if ( curve->points->npoints > 0 ) { size = curve->points->npoints * ptsize; memcpy(loc, getPoint_internal(curve->points, 0), size); loc += size; } return (size_t)(loc - buf); }
static size_t gserialized_from_lwpoint(const LWPOINT *point, uint8_t *buf) { uint8_t *loc; int ptsize = ptarray_point_size(point->point); int type = POINTTYPE; assert(point); assert(buf); if ( FLAGS_GET_ZM(point->flags) != FLAGS_GET_ZM(point->point->flags) ) lwerror("Dimensions mismatch in lwpoint"); LWDEBUGF(2, "lwpoint_to_gserialized(%p, %p) called", point, buf); loc = buf; /* Write in the type. */ memcpy(loc, &type, sizeof(uint32_t)); loc += sizeof(uint32_t); /* Write in the number of points (0 => empty). */ memcpy(loc, &(point->point->npoints), sizeof(uint32_t)); loc += sizeof(uint32_t); /* Copy in the ordinates. */ if ( point->point->npoints > 0 ) { memcpy(loc, getPoint_internal(point->point, 0), ptsize); loc += ptsize; } return (size_t)(loc - buf); }
static size_t gserialized_from_lwpoly(const LWPOLY *poly, uint8_t *buf) { int i; uint8_t *loc; int ptsize; int type = POLYGONTYPE; assert(poly); assert(buf); LWDEBUG(2, "lwpoly_to_gserialized called"); ptsize = sizeof(double) * FLAGS_NDIMS(poly->flags); loc = buf; /* Write in the type. */ memcpy(loc, &type, sizeof(uint32_t)); loc += sizeof(uint32_t); /* Write in the nrings. */ memcpy(loc, &(poly->nrings), sizeof(uint32_t)); loc += sizeof(uint32_t); /* Write in the npoints per ring. */ for ( i = 0; i < poly->nrings; i++ ) { memcpy(loc, &(poly->rings[i]->npoints), sizeof(uint32_t)); loc += sizeof(uint32_t); } /* Add in padding if necessary to remain double aligned. */ if ( poly->nrings % 2 ) { memset(loc, 0, sizeof(uint32_t)); loc += sizeof(uint32_t); } /* Copy in the ordinates. */ for ( i = 0; i < poly->nrings; i++ ) { POINTARRAY *pa = poly->rings[i]; size_t pasize; if ( FLAGS_GET_ZM(poly->flags) != FLAGS_GET_ZM(pa->flags) ) lwerror("Dimensions mismatch in lwpoly"); pasize = pa->npoints * ptsize; memcpy(loc, getPoint_internal(pa, 0), pasize); loc += pasize; } return (size_t)(loc - buf); }
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; }
int gbox_same(const GBOX *g1, const GBOX *g2) { if (FLAGS_GET_ZM(g1->flags) != FLAGS_GET_ZM(g2->flags)) return LW_FALSE; if (!gbox_same_2d(g1, g2)) return LW_FALSE; if (FLAGS_GET_Z(g1->flags) && (g1->zmin != g2->zmin || g1->zmax != g2->zmax)) return LW_FALSE; if (FLAGS_GET_M(g1->flags) && (g1->mmin != g2->mmin || g1->mmax != g2->mmax)) return LW_FALSE; return LW_TRUE; }
/* * Construct a LWCIRCSTRING from a LWMPOINT */ LWCIRCSTRING * lwcircstring_from_lwmpoint(int srid, LWMPOINT *mpoint) { uint32_t i; POINTARRAY *pa; char zmflag = FLAGS_GET_ZM(mpoint->flags); size_t ptsize, size; uint8_t *newpoints, *ptr; if (zmflag == 0) ptsize = 2 * sizeof(double); else if (zmflag == 3) ptsize = 4 * sizeof(double); else ptsize = 3 * sizeof(double); /* Allocate space for output points */ size = ptsize * mpoint->ngeoms; newpoints = lwalloc(size); memset(newpoints, 0, size); ptr = newpoints; for (i = 0; i < mpoint->ngeoms; i++) { memcpy(ptr, getPoint_internal(mpoint->geoms[i]->point, 0), ptsize); ptr += ptsize; } pa = ptarray_construct_reference_data(zmflag&2, zmflag&1, mpoint->ngeoms, newpoints); LWDEBUGF(3, "lwcurve_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag); return lwcircstring_construct(srid, NULL, pa); }
static size_t gserialized_from_lwtriangle(const LWTRIANGLE *triangle, uint8_t *buf) { uint8_t *loc; int ptsize; size_t size; int type = TRIANGLETYPE; assert(triangle); assert(buf); LWDEBUGF(2, "lwtriangle_to_gserialized(%p, %p) called", triangle, buf); if ( FLAGS_GET_ZM(triangle->flags) != FLAGS_GET_ZM(triangle->points->flags) ) lwerror("Dimensions mismatch in lwtriangle"); ptsize = ptarray_point_size(triangle->points); loc = buf; /* Write in the type. */ memcpy(loc, &type, sizeof(uint32_t)); loc += sizeof(uint32_t); /* Write in the npoints. */ memcpy(loc, &(triangle->points->npoints), sizeof(uint32_t)); loc += sizeof(uint32_t); LWDEBUGF(3, "lwtriangle_to_gserialized added npoints (%d)", triangle->points->npoints); /* Copy in the ordinates. */ if ( triangle->points->npoints > 0 ) { size = triangle->points->npoints * ptsize; memcpy(loc, getPoint_internal(triangle->points, 0), size); loc += size; } LWDEBUGF(3, "lwtriangle_to_gserialized copied serialized_pointlist (%d bytes)", ptsize * triangle->points->npoints); return (size_t)(loc - buf); }
/* 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; }
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2) { uint32_t i; size_t ptsize; if ( FLAGS_GET_ZM(pa1->flags) != FLAGS_GET_ZM(pa2->flags) ) return LW_FALSE; LWDEBUG(5,"dimensions are the same"); if ( pa1->npoints != pa2->npoints ) return LW_FALSE; LWDEBUG(5,"npoints are the same"); ptsize = ptarray_point_size(pa1); LWDEBUGF(5, "ptsize = %d", ptsize); for (i=0; i<pa1->npoints; i++) { if ( memcmp(getPoint_internal(pa1, i), getPoint_internal(pa2, i), ptsize) ) return LW_FALSE; LWDEBUGF(5,"point #%d is the same",i); } return LW_TRUE; }
/** * @brief geom1 same as geom2 * iff * + have same type * + have same # objects * + have same bvol * + each object in geom1 has a corresponding object in geom2 (see above) * @param lwgeom1 * @param lwgeom2 */ char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2) { LWDEBUGF(2, "lwgeom_same(%s, %s) called", lwtype_name(lwgeom1->type), lwtype_name(lwgeom2->type)); if ( lwgeom1->type != lwgeom2->type ) { LWDEBUG(3, " type differ"); return LW_FALSE; } if ( FLAGS_GET_ZM(lwgeom1->flags) != FLAGS_GET_ZM(lwgeom2->flags) ) { LWDEBUG(3, " ZM flags differ"); return LW_FALSE; } /* Check boxes if both already computed */ if ( lwgeom1->bbox && lwgeom2->bbox ) { /*lwnotice("bbox1:%p, bbox2:%p", lwgeom1->bbox, lwgeom2->bbox);*/ if ( ! gbox_same(lwgeom1->bbox, lwgeom2->bbox) ) { LWDEBUG(3, " bounding boxes differ"); return LW_FALSE; } } /* geoms have same type, invoke type-specific function */ switch (lwgeom1->type) { case POINTTYPE: return lwpoint_same((LWPOINT *)lwgeom1, (LWPOINT *)lwgeom2); case LINETYPE: return lwline_same((LWLINE *)lwgeom1, (LWLINE *)lwgeom2); case POLYGONTYPE: return lwpoly_same((LWPOLY *)lwgeom1, (LWPOLY *)lwgeom2); case TRIANGLETYPE: return lwtriangle_same((LWTRIANGLE *)lwgeom1, (LWTRIANGLE *)lwgeom2); case CIRCSTRINGTYPE: return lwcircstring_same((LWCIRCSTRING *)lwgeom1, (LWCIRCSTRING *)lwgeom2); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case COMPOUNDTYPE: case CURVEPOLYTYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: return lwcollection_same((LWCOLLECTION *)lwgeom1, (LWCOLLECTION *)lwgeom2); default: lwerror("lwgeom_same: unsupported geometry type: %s", lwtype_name(lwgeom1->type)); return LW_FALSE; } }
int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance) { unsigned int poff = 0; unsigned int npoints; unsigned int ncap; unsigned int ptsize; /* Check for pathology */ if( ! pa1 || ! pa2 ) { lwerror("ptarray_append_ptarray: null input"); return LW_FAILURE; } npoints = pa2->npoints; if ( ! npoints ) return LW_SUCCESS; /* nothing more to do */ if( FLAGS_GET_READONLY(pa1->flags) ) { lwerror("ptarray_append_ptarray: target pointarray is read-only"); return LW_FAILURE; } if( FLAGS_GET_ZM(pa1->flags) != FLAGS_GET_ZM(pa2->flags) ) { lwerror("ptarray_append_ptarray: appending mixed dimensionality is not allowed"); return LW_FAILURE; } ptsize = ptarray_point_size(pa1); /* Check for duplicate end point */ if ( pa1->npoints ) { POINT2D tmp1, tmp2; getPoint2d_p(pa1, pa1->npoints-1, &tmp1); getPoint2d_p(pa2, 0, &tmp2); /* If the end point and start point are the same, then don't copy start point */ if (p2d_same(&tmp1, &tmp2)) { poff = 1; --npoints; } else if ( gap_tolerance == 0 || ( gap_tolerance > 0 && distance2d_pt_pt(&tmp1, &tmp2) > gap_tolerance ) ) { lwerror("Second line start point too far from first line end point"); return LW_FAILURE; } } /* Check if we need extra space */ ncap = pa1->npoints + npoints; if ( pa1->maxpoints < ncap ) { pa1->maxpoints = ncap > pa1->maxpoints*2 ? ncap : pa1->maxpoints*2; pa1->serialized_pointlist = (uint8_t *)lwrealloc(pa1->serialized_pointlist, ptsize * pa1->maxpoints); } memcpy(getPoint_internal(pa1, pa1->npoints), getPoint_internal(pa2, poff), ptsize * npoints); pa1->npoints = ncap; return LW_SUCCESS; }