static int lwcircstring_calculate_gbox_cartesian(LWCIRCSTRING *curve, GBOX *gbox) { uint8_t flags = gflags(FLAGS_GET_Z(curve->flags), FLAGS_GET_M(curve->flags), 0); GBOX tmp; POINT4D p1, p2, p3; int i; if ( ! curve ) return LW_FAILURE; if ( curve->points->npoints < 3 ) return LW_FAILURE; tmp.flags = flags; /* Initialize */ gbox->xmin = gbox->ymin = gbox->zmin = gbox->mmin = MAXFLOAT; gbox->xmax = gbox->ymax = gbox->zmax = gbox->mmax = -1 * MAXFLOAT; for ( i = 2; i < curve->points->npoints; i += 2 ) { getPoint4d_p(curve->points, i-2, &p1); getPoint4d_p(curve->points, i-1, &p2); getPoint4d_p(curve->points, i, &p3); if (lw_arc_calculate_gbox_cartesian(&p1, &p2, &p3, &tmp) == LW_FAILURE) continue; gbox_merge(&tmp, gbox); } return LW_SUCCESS; }
static GBOX* parse_geohash(char *geohash, int precision) { GBOX *box = NULL; double lat[2], lon[2]; POSTGIS_DEBUG(2, "parse_geohash called."); if (NULL == geohash) { geohash_lwpgerror("invalid GeoHash representation", 2); } decode_geohash_bbox(geohash, lat, lon, precision); POSTGIS_DEBUGF(2, "ST_Box2dFromGeoHash sw: %.20f, %.20f", lon[0], lat[0]); POSTGIS_DEBUGF(2, "ST_Box2dFromGeoHash ne: %.20f, %.20f", lon[1], lat[1]); box = gbox_new(gflags(0, 0, 1)); box->xmin = lon[0]; box->ymin = lat[0]; box->xmax = lon[1]; box->ymax = lat[1]; POSTGIS_DEBUG(2, "parse_geohash finished."); return box; }
/** * Warning, this function is only good for x/y/z boxes, used * in unit testing of geodetic box generation. */ GBOX* gbox_from_string(const char *str) { const char *ptr = str; char *nextptr; char *gbox_start = strstr(str, "GBOX(("); GBOX *gbox = gbox_new(gflags(0,0,1)); if ( ! gbox_start ) return NULL; /* No header found */ ptr += 6; gbox->xmin = strtod(ptr, &nextptr); if ( ptr == nextptr ) return NULL; /* No double found */ ptr = nextptr + 1; gbox->ymin = strtod(ptr, &nextptr); if ( ptr == nextptr ) return NULL; /* No double found */ ptr = nextptr + 1; gbox->zmin = strtod(ptr, &nextptr); if ( ptr == nextptr ) return NULL; /* No double found */ ptr = nextptr + 3; gbox->xmax = strtod(ptr, &nextptr); if ( ptr == nextptr ) return NULL; /* No double found */ ptr = nextptr + 1; gbox->ymax = strtod(ptr, &nextptr); if ( ptr == nextptr ) return NULL; /* No double found */ ptr = nextptr + 1; gbox->zmax = strtod(ptr, &nextptr); if ( ptr == nextptr ) return NULL; /* No double found */ return gbox; }
static int lwcircstring_calculate_gbox(LWCIRCSTRING *curve, GBOX *gbox) { uchar flags = gflags(TYPE_HASZ(curve->type), TYPE_HASM(curve->type), 0); GBOX tmp; POINT4D p1, p2, p3; int i; if ( ! curve ) return G_FAILURE; if ( curve->points->npoints < 3 ) return G_FAILURE; tmp.flags = flags; /* Initialize */ gbox->xmin = gbox->ymin = gbox->zmin = gbox->mmin = MAXFLOAT; gbox->xmax = gbox->ymax = gbox->zmax = gbox->mmax = -1 * MAXFLOAT; for ( i = 2; i < curve->points->npoints; i += 2 ) { getPoint4d_p(curve->points, i-2, &p1); getPoint4d_p(curve->points, i-1, &p2); getPoint4d_p(curve->points, i, &p3); if (lwcircle_calculate_gbox(p1, p2, p3, &tmp) == G_FAILURE) continue; gbox_merge(&tmp, gbox); } return G_SUCCESS; }
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm) { LWPOINT *result = lwalloc(sizeof(LWPOINT)); result->type = POINTTYPE; result->flags = gflags(hasz, hasm, 0); result->srid = srid; result->point = ptarray_construct(hasz, hasm, 0); result->bbox = NULL; return result; }
/** * Build a new #POINTARRAY, but on top of someone else's ordinate array. * Flag as read-only, so that ptarray_free() does not free the serialized_ptlist */ POINTARRAY* ptarray_construct_reference_data(char hasz, char hasm, uint32_t npoints, uint8_t *ptlist) { POINTARRAY *pa = (POINTARRAY *)lwalloc(sizeof(POINTARRAY)); LWDEBUGF(5, "hasz = %d, hasm = %d, npoints = %d, ptlist = %p", hasz, hasm, npoints, ptlist); pa->flags = gflags(hasz, hasm, 0); FLAGS_SET_READONLY(pa->flags, 1); /* We don't own this memory, so we can't alter or free it. */ pa->npoints = npoints; pa->maxpoints = npoints; pa->serialized_pointlist = ptlist; return pa; }
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm) { LWCIRCSTRING *result = lwalloc(sizeof(LWCIRCSTRING)); result->type = CIRCSTRINGTYPE; result->flags = gflags(hasz,hasm,0); result->srid = srid; result->points = ptarray_construct_empty(hasz, hasm, 1); result->bbox = NULL; return result; }
LWTRIANGLE* lwtriangle_construct_empty(int srid, char hasz, char hasm) { LWTRIANGLE *result = lwalloc(sizeof(LWTRIANGLE)); result->type = TRIANGLETYPE; result->flags = gflags(hasz,hasm,0); result->srid = srid; result->points = ptarray_construct_empty(hasz, hasm, 1); result->bbox = NULL; return result; }
LWPOLY* lwpoly_construct_empty(int srid, char hasz, char hasm) { LWPOLY *result = lwalloc(sizeof(LWPOLY)); result->type = POLYGONTYPE; result->flags = gflags(hasz,hasm,0); result->srid = srid; result->nrings = 0; result->maxrings = 1; /* Allocate room for ring, just in case. */ result->rings = lwalloc(result->maxrings * sizeof(POINTARRAY*)); result->bbox = NULL; return result; }
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; }
LWCURVEPOLY * lwcurvepoly_construct_empty(int srid, char hasz, char hasm) { LWCURVEPOLY *ret; ret = (LWCURVEPOLY *)lwalloc(sizeof(LWCURVEPOLY)); ret->type = CURVEPOLYTYPE; ret->flags = gflags(hasz, hasm, 0); ret->srid = srid; ret->nrings = 0; ret->maxrings = 1; /* Allocate room for sub-members, just in case. */ ret->rings = (LWGEOM **)lwalloc(ret->maxrings * sizeof(LWGEOM*)); ret->bbox = NULL; return ret; }
Datum BOX2D_construct(PG_FUNCTION_ARGS) { GSERIALIZED *pgmin = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *pgmax = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); GBOX *result; LWPOINT *minpoint, *maxpoint; double min, max, tmp; minpoint = (LWPOINT*)lwgeom_from_gserialized(pgmin); maxpoint = (LWPOINT*)lwgeom_from_gserialized(pgmax); if ( (minpoint->type != POINTTYPE) || (maxpoint->type != POINTTYPE) ) { elog(ERROR, "GBOX_construct: arguments must be points"); PG_RETURN_NULL(); } error_if_srid_mismatch(minpoint->srid, maxpoint->srid); result = gbox_new(gflags(0, 0, 0)); /* Process X min/max */ min = lwpoint_get_x(minpoint); max = lwpoint_get_x(maxpoint); if ( min > max ) { tmp = min; min = max; max = tmp; } result->xmin = min; result->xmax = max; /* Process Y min/max */ min = lwpoint_get_y(minpoint); max = lwpoint_get_y(maxpoint); if ( min > max ) { tmp = min; min = max; max = tmp; } result->ymin = min; result->ymax = max; PG_RETURN_POINTER(result); }
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm) { LWCOLLECTION *ret; if( ! lwtype_is_collection(type) ) lwerror("Non-collection type specified in collection constructor!"); ret = lwalloc(sizeof(LWCOLLECTION)); ret->type = type; ret->flags = gflags(hasz,hasm,0); ret->srid = srid; ret->ngeoms = 0; ret->maxgeoms = 1; /* Allocate room for sub-members, just in case. */ ret->geoms = lwalloc(ret->maxgeoms * sizeof(LWGEOM*)); ret->bbox = NULL; return ret; }
int ptarray_calculate_gbox_cartesian(const POINTARRAY *pa, GBOX *gbox ) { int i; POINT4D p; int has_z, has_m; if ( ! pa ) return LW_FAILURE; if ( ! gbox ) return LW_FAILURE; if ( pa->npoints < 1 ) return LW_FAILURE; has_z = FLAGS_GET_Z(pa->flags); has_m = FLAGS_GET_M(pa->flags); gbox->flags = gflags(has_z, has_m, 0); LWDEBUGF(4, "ptarray_calculate_gbox Z: %d M: %d", has_z, has_m); getPoint4d_p(pa, 0, &p); gbox->xmin = gbox->xmax = p.x; gbox->ymin = gbox->ymax = p.y; if ( has_z ) gbox->zmin = gbox->zmax = p.z; if ( has_m ) gbox->mmin = gbox->mmax = p.m; for ( i = 1 ; i < pa->npoints; i++ ) { getPoint4d_p(pa, i, &p); gbox->xmin = FP_MIN(gbox->xmin, p.x); gbox->xmax = FP_MAX(gbox->xmax, p.x); gbox->ymin = FP_MIN(gbox->ymin, p.y); gbox->ymax = FP_MAX(gbox->ymax, p.y); if ( has_z ) { gbox->zmin = FP_MIN(gbox->zmin, p.z); gbox->zmax = FP_MAX(gbox->zmax, p.z); } if ( has_m ) { gbox->mmin = FP_MIN(gbox->mmin, p.m); gbox->mmax = FP_MAX(gbox->mmax, p.m); } } return LW_SUCCESS; }
POINTARRAY* ptarray_construct_copy_data(char hasz, char hasm, uint32_t npoints, const uint8_t *ptlist) { POINTARRAY *pa = (POINTARRAY *)lwalloc(sizeof(POINTARRAY)); pa->flags = gflags(hasz, hasm, 0); pa->npoints = npoints; pa->maxpoints = npoints; if ( npoints > 0 ) { pa->serialized_pointlist = (uint8_t *)lwalloc(ptarray_point_size(pa) * npoints); memcpy(pa->serialized_pointlist, ptlist, ptarray_point_size(pa) * npoints); } else { pa->serialized_pointlist = NULL; } return pa; }
POINTARRAY* ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints) { POINTARRAY *pa = lwalloc(sizeof(POINTARRAY)); pa->serialized_pointlist = NULL; /* Set our dimsionality info on the bitmap */ pa->flags = gflags(hasz, hasm, 0); /* We will be allocating a bit of room */ pa->npoints = 0; pa->maxpoints = maxpoints; /* Allocate the coordinate array */ if ( maxpoints > 0 ) pa->serialized_pointlist = lwalloc(maxpoints * ptarray_point_size(pa)); else pa->serialized_pointlist = NULL; return pa; }
/* 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; }
static double ptarray_area_spheroid(const POINTARRAY *pa, const SPHEROID *spheroid) { GEOGRAPHIC_POINT a, b; POINT2D p; int i; double area = 0.0; GBOX gbox2d; int in_south = LW_FALSE; double delta_lon_tolerance; double latitude_min; gbox2d.flags = gflags(0, 0, 0); /* Return zero on non-sensical inputs */ if ( ! pa || pa->npoints < 4 ) return 0.0; /* Get the raw min/max values for the latitudes */ ptarray_calculate_gbox(pa, &gbox2d); if ( signum(gbox2d.ymin) != signum(gbox2d.ymax) ) lwerror("ptarray_area_spheroid: cannot handle ptarray that crosses equator"); /* Geodetic bbox < 0.0 implies geometry is entirely in southern hemisphere */ if ( gbox2d.ymax < 0.0 ) in_south = LW_TRUE; LWDEBUGF(4, "gbox2d.ymax %.12g", gbox2d.ymax); /* Tolerance for strip area calculation */ if ( in_south ) { delta_lon_tolerance = (90.0 / (fabs(gbox2d.ymin) / 8.0) - 2.0) / 10000.0; latitude_min = deg2rad(fabs(gbox2d.ymax)); } else { delta_lon_tolerance = (90.0 / (fabs(gbox2d.ymax) / 8.0) - 2.0) / 10000.0; latitude_min = deg2rad(gbox2d.ymin); } /* Initialize first point */ getPoint2d_p(pa, 0, &p); geographic_point_init(p.x, p.y, &a); for ( i = 1; i < pa->npoints; i++ ) { GEOGRAPHIC_POINT a1, b1; double strip_area = 0.0; double delta_lon = 0.0; LWDEBUGF(4, "edge #%d", i); getPoint2d_p(pa, i, &p); geographic_point_init(p.x, p.y, &b); a1 = a; b1 = b; /* Flip into north if in south */ if ( in_south ) { a1.lat = -1.0 * a1.lat; b1.lat = -1.0 * b1.lat; } LWDEBUGF(4, "in_south %d", in_south); LWDEBUGF(4, "crosses_dateline(a, b) %d", crosses_dateline(&a, &b) ); if ( crosses_dateline(&a, &b) ) { double shift; if ( a1.lon > 0.0 ) shift = (M_PI - a1.lon) + 0.088; /* About 5deg more */ else shift = (M_PI - b1.lon) + 0.088; /* About 5deg more */ LWDEBUGF(4, "shift: %.8g", shift); LWDEBUGF(4, "before shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon); point_shift(&a1, shift); point_shift(&b1, shift); LWDEBUGF(4, "after shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon); } delta_lon = fabs(b1.lon - a1.lon); LWDEBUGF(4, "a1(%.18g %.18g) b1(%.18g %.18g)", a1.lat, a1.lon, b1.lat, b1.lon); LWDEBUGF(4, "delta_lon %.18g", delta_lon); LWDEBUGF(4, "delta_lon_tolerance %.18g", delta_lon_tolerance); if ( delta_lon > 0.0 ) { if ( delta_lon < delta_lon_tolerance ) { strip_area = spheroid_striparea(&a1, &b1, latitude_min, spheroid); LWDEBUGF(4, "strip_area %.12g", strip_area); area += strip_area; } else { GEOGRAPHIC_POINT p, q; double step = floor(delta_lon / delta_lon_tolerance); double distance = spheroid_distance(&a1, &b1, spheroid); double pDistance = 0.0; int j = 0; LWDEBUGF(4, "step %.18g", step); LWDEBUGF(4, "distance %.18g", distance); step = distance / step; LWDEBUGF(4, "step %.18g", step); p = a1; while (pDistance < (distance - step * 1.01)) { double azimuth = spheroid_direction(&p, &b1, spheroid); j++; LWDEBUGF(4, " iteration %d", j); LWDEBUGF(4, " azimuth %.12g", azimuth); pDistance = pDistance + step; LWDEBUGF(4, " pDistance %.12g", pDistance); spheroid_project(&p, spheroid, step, azimuth, &q); strip_area = spheroid_striparea(&p, &q, latitude_min, spheroid); LWDEBUGF(4, " strip_area %.12g", strip_area); area += strip_area; LWDEBUGF(4, " area %.12g", area); p.lat = q.lat; p.lon = q.lon; } strip_area = spheroid_striparea(&p, &b1, latitude_min, spheroid); area += strip_area; } } /* B gets incremented in the next loop, so we save the value here */ a = b; } return fabs(area); }