/* * Serialize a tgeom struct and return a * TSERIALIZED pointer */ TSERIALIZED * tgeom_serialize(const TGEOM *tgeom) { size_t size, retsize; TSERIALIZED * t; uint8_t *data; size = tgeom_serialize_size(tgeom); data = lwalloc(size); tgeom_serialize_buf(tgeom, data, &retsize); if ( retsize != size ) { lwerror("tgeom_serialize_size returned %d, ..serialize_buf returned %d", size, retsize); } t = lwalloc(sizeof(TSERIALIZED)); t->flags = tgeom->flags; t->srid = tgeom->srid; t->data = data; /* * We are aping PgSQL code here, PostGIS code should use * VARSIZE to set this for real. */ t->size = retsize << 2; return t; }
static void lwgeom_collect_endpoints(const LWGEOM* lwg, LWMPOINT* col) { int i, n; LWLINE* l; switch (lwg->type) { case MULTILINETYPE: for ( i = 0, n = lwgeom_ngeoms(lwg); i < n; ++i ) { lwgeom_collect_endpoints( lwgeom_subgeom(lwg, i), col); } break; case LINETYPE: l = (LWLINE*)lwg; col = lwmpoint_add_lwpoint(col, lwline_get_lwpoint(l, 0)); col = lwmpoint_add_lwpoint(col, lwline_get_lwpoint(l, l->points->npoints-1)); break; default: lwerror("lwgeom_collect_endpoints: invalid type %s", lwtype_name(lwg->type)); break; } }
/** * Find the area of the outer ring - sum (area of inner rings). */ double lwpoly_area(const LWPOLY *poly) { double poly_area = 0.0; int i; if ( ! poly ) lwerror("lwpoly_area called with null polygon pointer!"); for ( i=0; i < poly->nrings; i++ ) { POINTARRAY *ring = poly->rings[i]; double ringarea = 0.0; /* Empty or messed-up ring. */ if ( ring->npoints < 3 ) continue; ringarea = fabs(ptarray_signed_area(ring)); if ( i == 0 ) /* Outer ring, positive area! */ poly_area += ringarea; else /* Inner ring, negative area! */ poly_area -= ringarea; } return poly_area; }
LWMLINE * lwmcurve_segmentize(LWMCURVE *mcurve, uint32_t perQuad) { LWMLINE *ogeom; LWGEOM *tmp; LWGEOM **lines; int i; LWDEBUGF(2, "lwmcurve_segmentize called, geoms=%d, dim=%d.", mcurve->ngeoms, FLAGS_NDIMS(mcurve->flags)); lines = lwalloc(sizeof(LWGEOM *)*mcurve->ngeoms); for (i = 0; i < mcurve->ngeoms; i++) { tmp = mcurve->geoms[i]; if (tmp->type == CIRCSTRINGTYPE) { lines[i] = (LWGEOM *)lwcircstring_segmentize((LWCIRCSTRING *)tmp, perQuad); } else if (tmp->type == LINETYPE) { lines[i] = (LWGEOM *)lwline_construct(mcurve->srid, NULL, ptarray_clone_deep(((LWLINE *)tmp)->points)); } else { lwerror("Unsupported geometry found in MultiCurve."); return NULL; } } ogeom = (LWMLINE *)lwcollection_construct(MULTILINETYPE, mcurve->srid, NULL, mcurve->ngeoms, lines); return ogeom; }
/** * Deep-clone an #LWGEOM object. #POINTARRAY <em>are</em> copied. */ LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom) { LWDEBUGF(2, "lwgeom_clone called with %p, %s", lwgeom, lwtype_name(lwgeom->type)); switch (lwgeom->type) { case POINTTYPE: case LINETYPE: case CIRCSTRINGTYPE: case TRIANGLETYPE: return (LWGEOM *)lwline_clone_deep((LWLINE *)lwgeom); case POLYGONTYPE: return (LWGEOM *)lwpoly_clone_deep((LWPOLY *)lwgeom); case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: return (LWGEOM *)lwcollection_clone_deep((LWCOLLECTION *)lwgeom); default: lwerror("lwgeom_clone_deep: Unknown geometry type: %s", lwtype_name(lwgeom->type)); return NULL; } }
/** * @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; }
/* * Integer32 */ static uint8_t* integer_to_wkb_buf(const int ival, uint8_t *buf, uint8_t variant) { char *iptr = (char*)(&ival); int i = 0; if ( sizeof(int) != WKB_INT_SIZE ) { lwerror("Machine int size is not %d bytes!", WKB_INT_SIZE); } LWDEBUGF(4, "Writing value '%u'", ival); if ( variant & WKB_HEX ) { int swap = wkb_swap_bytes(variant); /* Machine/request arch mismatch, so flip byte order */ for ( i = 0; i < WKB_INT_SIZE; i++ ) { int j = (swap ? WKB_INT_SIZE - 1 - i : i); uint8_t b = iptr[j]; /* Top four bits to 0-F */ buf[2*i] = hexchr[b >> 4]; /* Bottom four bits to 0-F */ buf[2*i+1] = hexchr[b & 0x0F]; } return buf + (2 * WKB_INT_SIZE); }
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_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); }
Datum LWGEOM_m_point(PG_FUNCTION_ARGS) { GSERIALIZED *geom; LWPOINT *point = NULL; LWGEOM *lwgeom; POINT3DM p; geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); if ( gserialized_get_type(geom) != POINTTYPE ) lwerror("Argument to M() must be a point"); lwgeom = lwgeom_from_gserialized(geom); point = lwgeom_as_lwpoint(lwgeom); if ( lwgeom_is_empty(lwgeom) ) PG_RETURN_NULL(); /* no M in input */ if ( ! FLAGS_GET_M(point->flags) ) PG_RETURN_NULL(); getPoint3dm_p(point->point, 0, &p); PG_FREE_IF_COPY(geom, 0); PG_RETURN_FLOAT8(p.m); }
static size_t gserialized_from_any_size(const LWGEOM *geom) { LWDEBUGF(2, "Input type: %s", lwtype_name(geom->type)); switch (geom->type) { case POINTTYPE: return gserialized_from_lwpoint_size((LWPOINT *)geom); case LINETYPE: return gserialized_from_lwline_size((LWLINE *)geom); case POLYGONTYPE: return gserialized_from_lwpoly_size((LWPOLY *)geom); case TRIANGLETYPE: return gserialized_from_lwtriangle_size((LWTRIANGLE *)geom); case CIRCSTRINGTYPE: return gserialized_from_lwcircstring_size((LWCIRCSTRING *)geom); case CURVEPOLYTYPE: case COMPOUNDTYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTICURVETYPE: case MULTIPOLYGONTYPE: case MULTISURFACETYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: return gserialized_from_lwcollection_size((LWCOLLECTION *)geom); default: lwerror("Unknown geometry type: %d - %s", geom->type, lwtype_name(geom->type)); return 0; } }
LWGEOM * lwcurvepoly_add(const LWCURVEPOLY *to, uint32 where, const LWGEOM *what) { /* TODO */ lwerror("lwcurvepoly_add not yet implemented."); return NULL; }
CIRC_NODE* lwgeom_calculate_circ_tree(const LWGEOM* lwgeom) { if ( lwgeom_is_empty(lwgeom) ) return NULL; switch ( lwgeom->type ) { case POINTTYPE: return lwpoint_calculate_circ_tree((LWPOINT*)lwgeom); case LINETYPE: return lwline_calculate_circ_tree((LWLINE*)lwgeom); case POLYGONTYPE: return lwpoly_calculate_circ_tree((LWPOLY*)lwgeom); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return lwcollection_calculate_circ_tree((LWCOLLECTION*)lwgeom); default: lwerror("Unable to calculate spherical index tree for type %s", lwtype_name(lwgeom->type)); return NULL; } }
/* * Compute 2D/3D perimeter of a TGEOM */ double tgeom_perimeter(TGEOM* tgeom) { int i; double hz, vt, ht, bdy = 0.0; assert(tgeom); if (tgeom->type != POLYHEDRALSURFACETYPE && tgeom->type != TINTYPE) lwerror("tgeom_perimeter called with wrong type: %i - %s", tgeom->type, lwtype_name(tgeom->type)); /* Solid have a 0.0 length perimeter */ if (FLAGS_GET_SOLID(tgeom->flags)) return bdy; /* If no Z use 2d function instead */ if (!FLAGS_GET_Z(tgeom->flags)) return tgeom_perimeter2d(tgeom); for (i=1 ; i <= tgeom->nedges ; i++) { if (tgeom->edges[i]->count == 1) { hz = tgeom->edges[i]->s->x - tgeom->edges[i]->e->x; vt = tgeom->edges[i]->s->y - tgeom->edges[i]->e->y; ht = tgeom->edges[i]->s->z - tgeom->edges[i]->e->z; bdy += sqrt(hz*hz + vt*vt + ht*ht); } } return bdy; }
Datum ST_AddMeasure(PG_FUNCTION_ARGS) { GSERIALIZED *gin = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *gout; double start_measure = PG_GETARG_FLOAT8(1); double end_measure = PG_GETARG_FLOAT8(2); LWGEOM *lwin, *lwout; int type = gserialized_get_type(gin); /* Raise an error if input is not a linestring or multilinestring */ if ( type != LINETYPE && type != MULTILINETYPE ) { lwerror("Only LINESTRING and MULTILINESTRING are supported"); PG_RETURN_NULL(); } lwin = lwgeom_from_gserialized(gin); if ( type == LINETYPE ) lwout = (LWGEOM*)lwline_measured_from_lwline((LWLINE*)lwin, start_measure, end_measure); else lwout = (LWGEOM*)lwmline_measured_from_lwmline((LWMLINE*)lwin, start_measure, end_measure); lwgeom_release(lwin); if ( lwout == NULL ) PG_RETURN_NULL(); gout = geometry_serialize(lwout); lwgeom_release(lwout); PG_RETURN_POINTER(gout); }
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); }
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int repeated_points) { /* Check for pathology */ if( ! pa || ! pt ) { lwerror("ptarray_append_point: null input"); return LW_FAILURE; } /* Check for duplicate end point */ if ( repeated_points == LW_FALSE && pa->npoints > 0 ) { POINT4D tmp; getPoint4d_p(pa, pa->npoints-1, &tmp); LWDEBUGF(4,"checking for duplicate end point (pt = POINT(%g %g) pa->npoints-q = POINT(%g %g))",pt->x,pt->y,tmp.x,tmp.y); /* Return LW_SUCCESS and do nothing else if previous point in list is equal to this one */ if ( (pt->x == tmp.x) && (pt->y == tmp.y) && (FLAGS_GET_Z(pa->flags) ? pt->z == tmp.z : 1) && (FLAGS_GET_M(pa->flags) ? pt->m == tmp.m : 1) ) { return LW_SUCCESS; } } /* Append is just a special case of insert */ return ptarray_insert_point(pa, pt, pa->npoints); }
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox) { if ( ! lwgeom ) return LW_FAILURE; LWDEBUGF(4, "lwgeom_calculate_gbox got type (%d) - %s", lwgeom->type, lwtype_name(lwgeom->type)); switch (lwgeom->type) { case POINTTYPE: return lwpoint_calculate_gbox_cartesian((LWPOINT *)lwgeom, gbox); case LINETYPE: return lwline_calculate_gbox_cartesian((LWLINE *)lwgeom, gbox); case CIRCSTRINGTYPE: return lwcircstring_calculate_gbox_cartesian((LWCIRCSTRING *)lwgeom, gbox); case POLYGONTYPE: return lwpoly_calculate_gbox_cartesian((LWPOLY *)lwgeom, gbox); case TRIANGLETYPE: return lwtriangle_calculate_gbox_cartesian((LWTRIANGLE *)lwgeom, gbox); case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTICURVETYPE: case MULTIPOLYGONTYPE: case MULTISURFACETYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: return lwcollection_calculate_gbox_cartesian((LWCOLLECTION *)lwgeom, gbox); } /* Never get here, please. */ lwerror("unsupported type (%d) - %s", lwgeom->type, lwtype_name(lwgeom->type)); return LW_FAILURE; }
/* * Construct a new LWCIRCSTRING. points will *NOT* be copied * use SRID=-1 for unknown SRID (will have 8bit type's S = 0) */ LWCIRCSTRING * lwcircstring_construct(int SRID, BOX2DFLOAT4 *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) { lwerror("lwcircstring_construct: invalid point count %d", points->npoints); return NULL; } result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING)); result->type = lwgeom_makeType_full( TYPE_HASZ(points->dims), TYPE_HASM(points->dims), (SRID!=-1), CIRCSTRINGTYPE, 0); result->SRID = SRID; result->points = points; result->bbox = bbox; return result; }
static uint32_t lwtype_from_twkb_type(uint8_t twkb_type) { switch (twkb_type) { case 1: return POINTTYPE; case 2: return LINETYPE; case 3: return POLYGONTYPE; case 4: return MULTIPOINTTYPE; case 5: return MULTILINETYPE; case 6: return MULTIPOLYGONTYPE; case 7: return COLLECTIONTYPE; default: /* Error! */ lwerror("Unknown WKB type"); return 0; } return 0; }
/* * GeometryType, and dimensions */ static uint8_t lwgeom_twkb_type(const LWGEOM *geom) { uint8_t twkb_type = 0; LWDEBUGF(2, "Entered lwgeom_twkb_type",0); switch ( geom->type ) { case POINTTYPE: twkb_type = WKB_POINT_TYPE; break; case LINETYPE: twkb_type = WKB_LINESTRING_TYPE; break; case POLYGONTYPE: twkb_type = WKB_POLYGON_TYPE; break; case MULTIPOINTTYPE: twkb_type = WKB_MULTIPOINT_TYPE; break; case MULTILINETYPE: twkb_type = WKB_MULTILINESTRING_TYPE; break; case MULTIPOLYGONTYPE: twkb_type = WKB_MULTIPOLYGON_TYPE; break; case COLLECTIONTYPE: twkb_type = WKB_GEOMETRYCOLLECTION_TYPE; break; default: lwerror("Unsupported geometry type: %s [%d]", lwtype_name(geom->type), geom->type); } return twkb_type; }
/** * LINESTRING */ static LWLINE* lwline_from_twkb_state(twkb_parse_state *s) { uint32_t npoints; POINTARRAY *pa; LWDEBUG(2,"Entering lwline_from_twkb_state"); if ( s->is_empty ) return lwline_construct_empty(SRID_UNKNOWN, s->has_z, s->has_m); /* Read number of points */ npoints = twkb_parse_state_uvarint(s); if ( npoints == 0 ) return lwline_construct_empty(SRID_UNKNOWN, s->has_z, s->has_m); /* Read coordinates */ pa = ptarray_from_twkb_state(s, npoints); if( pa == NULL ) return lwline_construct_empty(SRID_UNKNOWN, s->has_z, s->has_m); if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 ) { lwerror("%s must have at least two points", lwtype_name(s->lwtype)); return NULL; } return lwline_construct(SRID_UNKNOWN, NULL, pa); }
LWGEOM * lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm) { switch(type) { case POINTTYPE: return lwpoint_as_lwgeom(lwpoint_construct_empty(srid, hasz, hasm)); case LINETYPE: return lwline_as_lwgeom(lwline_construct_empty(srid, hasz, hasm)); case POLYGONTYPE: return lwpoly_as_lwgeom(lwpoly_construct_empty(srid, hasz, hasm)); case CURVEPOLYTYPE: return lwcurvepoly_as_lwgeom(lwcurvepoly_construct_empty(srid, hasz, hasm)); case CIRCSTRINGTYPE: return lwcircstring_as_lwgeom(lwcircstring_construct_empty(srid, hasz, hasm)); case TRIANGLETYPE: return lwtriangle_as_lwgeom(lwtriangle_construct_empty(srid, hasz, hasm)); case COMPOUNDTYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return lwcollection_as_lwgeom(lwcollection_construct_empty(type, srid, hasz, hasm)); default: lwerror("lwgeom_construct_empty: unsupported geometry type: %s", lwtype_name(type)); return NULL; } }
/** * MULTIPOLYGON */ static LWCOLLECTION* lwmultipoly_from_twkb_state(twkb_parse_state *s) { int ngeoms, i; LWGEOM *geom = NULL; LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, SRID_UNKNOWN, s->has_z, s->has_m); LWDEBUG(2,"Entering lwmultipolygon_from_twkb_state"); if ( s->is_empty ) return col; /* Read number of geometries */ ngeoms = twkb_parse_state_uvarint(s); LWDEBUGF(4,"Number of geometries %d",ngeoms); /* It has an idlist, we need to skip that */ if ( s->has_idlist ) { for ( i = 0; i < ngeoms; i++ ) twkb_parse_state_varint_skip(s); } for ( i = 0; i < ngeoms; i++ ) { geom = lwpoly_as_lwgeom(lwpoly_from_twkb_state(s)); if ( lwcollection_add_lwgeom(col, geom) == NULL ) { lwerror("Unable to add geometry (%p) to collection (%p)", geom, col); return NULL; } } return col; }
LWGEOM* lwgeom_force_dims(const LWGEOM *geom, int hasz, int hasm) { switch(geom->type) { case POINTTYPE: return lwpoint_as_lwgeom(lwpoint_force_dims((LWPOINT*)geom, hasz, hasm)); case CIRCSTRINGTYPE: case LINETYPE: case TRIANGLETYPE: return lwline_as_lwgeom(lwline_force_dims((LWLINE*)geom, hasz, hasm)); case POLYGONTYPE: return lwpoly_as_lwgeom(lwpoly_force_dims((LWPOLY*)geom, hasz, hasm)); case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: return lwcollection_as_lwgeom(lwcollection_force_dims((LWCOLLECTION*)geom, hasz, hasm)); default: lwerror("lwgeom_force_2d: unsupported geom type: %s", lwtype_name(geom->type)); return NULL; } }
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox) { if ( ! lwgeom ) return G_FAILURE; switch (TYPE_GETTYPE(lwgeom->type)) { case POINTTYPE: return lwpoint_calculate_gbox((LWPOINT *)lwgeom, gbox); case LINETYPE: return lwline_calculate_gbox((LWLINE *)lwgeom, gbox); case CIRCSTRINGTYPE: return lwcircstring_calculate_gbox((LWCIRCSTRING *)lwgeom, gbox); case POLYGONTYPE: return lwpoly_calculate_gbox((LWPOLY *)lwgeom, gbox); case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTICURVETYPE: case MULTIPOLYGONTYPE: case MULTISURFACETYPE: case COLLECTIONTYPE: return lwcollection_calculate_gbox((LWCOLLECTION *)lwgeom, gbox); } /* Never get here, please. */ lwerror("unsupported type (%d)", TYPE_GETTYPE(lwgeom->type)); return G_FAILURE; }
LWPOINT* lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, int where) { int i; int count = 0; int npoints = 0; if ( lwgeom_is_empty((LWGEOM*)lwcmp) ) return NULL; npoints = lwgeom_count_vertices((LWGEOM*)lwcmp); if ( where < 0 || where >= npoints ) { lwerror("%s: index %d is not in range of number of vertices (%d) in input", __func__, where, npoints); return NULL; } for ( i = 0; i < lwcmp->ngeoms; i++ ) { LWGEOM* part = lwcmp->geoms[i]; int npoints_part = lwgeom_count_vertices(part); if ( where >= count && where < count + npoints_part ) { return lwline_get_lwpoint((LWLINE*)part, where - count); } else { count += npoints_part; } } return NULL; }
/** * COLLECTION, MULTIPOINTTYPE, MULTILINETYPE, MULTIPOLYGONTYPE, COMPOUNDTYPE, * MULTICURVETYPE, MULTISURFACETYPE, * TINTYPE */ static LWCOLLECTION* lwcollection_from_wkb_state(wkb_parse_state *s) { uint32_t ngeoms = integer_from_wkb_state(s); LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, s->srid, s->has_z, s->has_m); LWGEOM *geom = NULL; int i; LWDEBUGF(4,"Collection has %d components", ngeoms); /* Empty collection? */ if ( ngeoms == 0 ) return col; /* Be strict in polyhedral surface closures */ if ( s->lwtype == POLYHEDRALSURFACETYPE ) s->check |= LW_PARSER_CHECK_ZCLOSURE; for ( i = 0; i < ngeoms; i++ ) { geom = lwgeom_from_wkb_state(s); if ( lwcollection_add_lwgeom(col, geom) == NULL ) { lwerror("Unable to add geometry (%p) to collection (%p)", geom, col); return NULL; } } return col; }
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; }
/** Function initializing closestpoint calculations. */ LWGEOM * lw_dist2d_distancepoint(LWGEOM *lw1, LWGEOM *lw2,int srid,int mode) { double x,y; DISTPTS thedl; double initdistance = MAXFLOAT; LWGEOM *result; thedl.mode = mode; thedl.distance= initdistance; thedl.tolerance = 0; LWDEBUG(2, "lw_dist2d_distancepoint is called"); if (!lw_dist2d_comp( lw1,lw2,&thedl)) { /*should never get here. all cases ought to be error handled earlier*/ lwerror("Some unspecified error."); result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0); } if (thedl.distance == initdistance) { LWDEBUG(3, "didn't find geometries to measure between, returning null"); result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0); } else { x=thedl.p1.x; y=thedl.p1.y; result = (LWGEOM *)lwpoint_make2d(srid, x, y); } return result; }