aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/geo_ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/geo_ops.c')
-rw-r--r--src/backend/utils/adt/geo_ops.c903
1 files changed, 339 insertions, 564 deletions
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 37dff3b9089..5eef1458aa2 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.52 2000/06/14 18:17:42 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.53 2000/07/29 18:45:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -41,7 +41,6 @@ static CIRCLE *circle_copy(CIRCLE *circle);
static LINE *line_construct_pm(Point *pt, double m);
static double lseg_dt(LSEG *l1, LSEG *l2);
static void make_bound_box(POLYGON *poly);
-static PATH *path_copy(PATH *path);
static bool plist_same(int npts, Point *p1, Point *p2);
static Point *point_construct(double x, double y);
static Point *point_copy(Point *pt);
@@ -434,9 +433,9 @@ box_fill(BOX *result, double x1, double x2, double y1, double y2)
static BOX *
box_copy(BOX *box)
{
- BOX *result = palloc(sizeof(BOX));
+ BOX *result = (BOX *) palloc(sizeof(BOX));
- memmove((char *) result, (char *) box, sizeof(BOX));
+ memcpy((char *) result, (char *) box, sizeof(BOX));
return result;
}
@@ -1139,20 +1138,17 @@ line_interpt(LINE *l1, LINE *l2)
* "(closed, npts, xcoord, ycoord,... )"
*---------------------------------------------------------*/
-PATH *
-path_in(char *str)
+Datum
+path_in(PG_FUNCTION_ARGS)
{
+ char *str = PG_GETARG_CSTRING(0);
PATH *path;
-
int isopen;
char *s;
int npts;
int size;
int depth = 0;
- if (!PointerIsValid(str))
- elog(ERROR, "Bad (null) path external representation");
-
if ((npts = pair_count(str, ',')) <= 0)
elog(ERROR, "Bad path external representation '%s'", str);
@@ -1167,7 +1163,7 @@ path_in(char *str)
depth++;
}
- size = offsetof(PATH, p[0]) +(sizeof(path->p[0]) * npts);
+ size = offsetof(PATH, p[0]) + sizeof(path->p[0]) * npts;
path = palloc(size);
path->size = size;
@@ -1179,18 +1175,17 @@ path_in(char *str)
path->closed = (!isopen);
- return path;
-} /* path_in() */
+ PG_RETURN_PATH_P(path);
+}
-char *
-path_out(PATH *path)
+Datum
+path_out(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(path))
- return NULL;
+ PATH *path = PG_GETARG_PATH_P(0);
- return path_encode(path->closed, path->npts, (Point *) &(path->p[0]));
-} /* path_out() */
+ PG_RETURN_CSTRING(path_encode(path->closed, path->npts, path->p));
+}
/*----------------------------------------------------------
@@ -1201,111 +1196,99 @@ path_out(PATH *path)
* Better relops and access methods coming soon.
*---------------------------------------------------------*/
-bool
-path_n_lt(PATH *p1, PATH *p2)
+Datum
+path_n_lt(PG_FUNCTION_ARGS)
{
- return (p1->npts < p2->npts);
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
+
+ PG_RETURN_BOOL(p1->npts < p2->npts);
}
-bool
-path_n_gt(PATH *p1, PATH *p2)
+Datum
+path_n_gt(PG_FUNCTION_ARGS)
{
- return (p1->npts > p2->npts);
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
+
+ PG_RETURN_BOOL(p1->npts > p2->npts);
}
-bool
-path_n_eq(PATH *p1, PATH *p2)
+Datum
+path_n_eq(PG_FUNCTION_ARGS)
{
- return (p1->npts == p2->npts);
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
+
+ PG_RETURN_BOOL(p1->npts == p2->npts);
}
-bool
-path_n_le(PATH *p1, PATH *p2)
+Datum
+path_n_le(PG_FUNCTION_ARGS)
{
- return (p1->npts <= p2->npts);
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
+
+ PG_RETURN_BOOL(p1->npts <= p2->npts);
}
-bool
-path_n_ge(PATH *p1, PATH *p2)
+Datum
+path_n_ge(PG_FUNCTION_ARGS)
{
- return (p1->npts >= p2->npts);
-}
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
+ PG_RETURN_BOOL(p1->npts >= p2->npts);
+}
/*----------------------------------------------------------
* Conversion operators.
*---------------------------------------------------------*/
-bool
-path_isclosed(PATH *path)
-{
- if (!PointerIsValid(path))
- return FALSE;
-
- return path->closed;
-} /* path_isclosed() */
-
-bool
-path_isopen(PATH *path)
+Datum
+path_isclosed(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(path))
- return FALSE;
-
- return !path->closed;
-} /* path_isopen() */
+ PATH *path = PG_GETARG_PATH_P(0);
+ PG_RETURN_BOOL(path->closed);
+}
-int4
-path_npoints(PATH *path)
+Datum
+path_isopen(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(path))
- return 0;
+ PATH *path = PG_GETARG_PATH_P(0);
- return path->npts;
-} /* path_npoints() */
+ PG_RETURN_BOOL(! path->closed);
+}
-PATH *
-path_close(PATH *path)
+Datum
+path_npoints(PG_FUNCTION_ARGS)
{
- PATH *result;
-
- if (!PointerIsValid(path))
- return NULL;
+ PATH *path = PG_GETARG_PATH_P(0);
- result = path_copy(path);
- result->closed = TRUE;
-
- return result;
-} /* path_close() */
+ PG_RETURN_INT32(path->npts);
+}
-PATH *
-path_open(PATH *path)
+Datum
+path_close(PG_FUNCTION_ARGS)
{
- PATH *result;
-
- if (!PointerIsValid(path))
- return NULL;
-
- result = path_copy(path);
- result->closed = FALSE;
+ PATH *path = PG_GETARG_PATH_P_COPY(0);
- return result;
-} /* path_open() */
+ path->closed = TRUE;
+ PG_RETURN_PATH_P(path);
+}
-static PATH *
-path_copy(PATH *path)
+Datum
+path_open(PG_FUNCTION_ARGS)
{
- PATH *result;
- int size;
+ PATH *path = PG_GETARG_PATH_P_COPY(0);
- size = offsetof(PATH, p[0]) +(sizeof(path->p[0]) * path->npts);
- result = palloc(size);
+ path->closed = FALSE;
- memmove((char *) result, (char *) path, size);
- return result;
-} /* path_copy() */
+ PG_RETURN_PATH_P(path);
+}
/* path_inter -
@@ -1313,9 +1296,11 @@ path_copy(PATH *path)
* Use bounding boxes for a quick (O(n)) check, then do a
* O(n^2) iterative edge check.
*/
-bool
-path_inter(PATH *p1, PATH *p2)
+Datum
+path_inter(PG_FUNCTION_ARGS)
{
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
BOX b1,
b2;
int i,
@@ -1342,7 +1327,7 @@ path_inter(PATH *p1, PATH *p2)
b2.low.y = Min(p2->p[i].y, b2.low.y);
}
if (!box_overlap(&b1, &b2))
- return FALSE;
+ PG_RETURN_BOOL(false);
/* pairwise check lseg intersections */
for (i = 0; i < p1->npts - 1; i++)
@@ -1352,90 +1337,71 @@ path_inter(PATH *p1, PATH *p2)
statlseg_construct(&seg1, &p1->p[i], &p1->p[i + 1]);
statlseg_construct(&seg2, &p2->p[j], &p2->p[j + 1]);
if (lseg_intersect(&seg1, &seg2))
- return TRUE;
+ PG_RETURN_BOOL(true);
}
}
/* if we dropped through, no two segs intersected */
- return FALSE;
-} /* path_inter() */
+ PG_RETURN_BOOL(false);
+}
/* path_distance()
* This essentially does a cartesian product of the lsegs in the
- * two paths, and finds the min distance between any two lsegs
+ * two paths, and finds the max distance between any two lsegs
*/
-double *
-path_distance(PATH *p1, PATH *p2)
+Datum
+path_distance(PG_FUNCTION_ARGS)
{
- double *min = NULL,
- *tmp;
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
+ bool have_max = false;
+ float8 max = 0.0; /* initialize to keep compiler quiet */
+ float8 tmp;
int i,
j;
LSEG seg1,
seg2;
-/*
- statlseg_construct(&seg1, &p1->p[0], &p1->p[1]);
- statlseg_construct(&seg2, &p2->p[0], &p2->p[1]);
- min = lseg_distance(&seg1, &seg2);
-*/
-
for (i = 0; i < p1->npts - 1; i++)
+ {
for (j = 0; j < p2->npts - 1; j++)
{
statlseg_construct(&seg1, &p1->p[i], &p1->p[i + 1]);
statlseg_construct(&seg2, &p2->p[j], &p2->p[j + 1]);
- tmp = lseg_distance(&seg1, &seg2);
- if ((min == NULL) || (*min < *tmp))
+ tmp = *lseg_distance(&seg1, &seg2);
+ if (!have_max || max < tmp)
{
- if (min != NULL)
- pfree(min);
- min = tmp;
+ max = tmp;
+ have_max = true;
}
- else
- pfree(tmp);
}
+ }
- return min;
-} /* path_distance() */
+ if (! have_max)
+ PG_RETURN_NULL();
+
+ PG_RETURN_FLOAT8(max);
+}
/*----------------------------------------------------------
* "Arithmetic" operations.
*---------------------------------------------------------*/
-double *
-path_length(PATH *path)
-{
- double *result;
- int i;
-
- result = palloc(sizeof(double));
-
- *result = 0;
- for (i = 0; i < (path->npts - 1); i++)
- *result += point_dt(&path->p[i], &path->p[i + 1]);
-
- return result;
-} /* path_length() */
-
-
-#ifdef NOT_USED
-double
-path_ln(PATH *path)
+Datum
+path_length(PG_FUNCTION_ARGS)
{
- double result;
+ PATH *path = PG_GETARG_PATH_P(0);
+ float8 result;
int i;
- result = 0;
+ result = 0.0;
for (i = 0; i < (path->npts - 1); i++)
result += point_dt(&path->p[i], &path->p[i + 1]);
- return result;
-} /* path_ln() */
-
-#endif
+ PG_RETURN_FLOAT8(result);
+}
/***********************************************************************
**
@@ -2058,11 +2024,13 @@ dist_ps(Point *pt, LSEG *lseg)
/*
** Distance from a point to a path
*/
-double *
-dist_ppath(Point *pt, PATH *path)
+Datum
+dist_ppath(PG_FUNCTION_ARGS)
{
- double *result;
- double *tmp;
+ Point *pt = PG_GETARG_POINT_P(0);
+ PATH *path = PG_GETARG_PATH_P(1);
+ float8 result = 0.0; /* keep compiler quiet */
+ float8 tmp;
int i;
LSEG lseg;
@@ -2070,11 +2038,10 @@ dist_ppath(Point *pt, PATH *path)
{
/* no points in path? then result is undefined... */
case 0:
- result = NULL;
- break;
+ PG_RETURN_NULL();
/* one point in path? then get distance between two points... */
case 1:
- result = point_distance(pt, &path->p[0]);
+ result = *point_distance(pt, &path->p[0]);
break;
default:
/* make sure the path makes sense... */
@@ -2084,18 +2051,16 @@ dist_ppath(Point *pt, PATH *path)
* the distance from a point to a path is the smallest
* distance from the point to any of its constituent segments.
*/
- result = palloc(sizeof(double));
for (i = 0; i < path->npts - 1; i++)
{
statlseg_construct(&lseg, &path->p[i], &path->p[i + 1]);
- tmp = dist_ps(pt, &lseg);
- if (i == 0 || *tmp < *result)
- *result = *tmp;
- pfree(tmp);
+ tmp = *dist_ps(pt, &lseg);
+ if (i == 0 || tmp < result)
+ result = tmp;
}
break;
}
- return result;
+ PG_RETURN_FLOAT8(result);
}
double *
@@ -2185,26 +2150,22 @@ dist_lb(LINE *line, BOX *box)
}
-double *
-dist_cpoly(CIRCLE *circle, POLYGON *poly)
+Datum
+dist_cpoly(PG_FUNCTION_ARGS)
{
- double *result;
+ CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
+ POLYGON *poly = PG_GETARG_POLYGON_P(1);
+ float8 result;
+ float8 d;
int i;
- double *d;
LSEG seg;
- if (!PointerIsValid(circle) || !PointerIsValid(poly))
- elog(ERROR, "Invalid (null) input for distance");
-
- if (point_inside(&(circle->center), poly->npts, poly->p))
+ if (point_inside(&(circle->center), poly->npts, poly->p) != 0)
{
#ifdef GEODEBUG
printf("dist_cpoly- center inside of polygon\n");
#endif
- result = palloc(sizeof(double));
-
- *result = 0;
- return result;
+ PG_RETURN_FLOAT8(0.0);
}
/* initialize distance with segment between first and last points */
@@ -2212,9 +2173,9 @@ dist_cpoly(CIRCLE *circle, POLYGON *poly)
seg.p[0].y = poly->p[0].y;
seg.p[1].x = poly->p[poly->npts - 1].x;
seg.p[1].y = poly->p[poly->npts - 1].y;
- result = dist_ps(&(circle->center), &seg);
+ result = *dist_ps(&(circle->center), &seg);
#ifdef GEODEBUG
- printf("dist_cpoly- segment 0/n distance is %f\n", *result);
+ printf("dist_cpoly- segment 0/n distance is %f\n", result);
#endif
/* check distances for other segments */
@@ -2224,21 +2185,20 @@ dist_cpoly(CIRCLE *circle, POLYGON *poly)
seg.p[0].y = poly->p[i].y;
seg.p[1].x = poly->p[i + 1].x;
seg.p[1].y = poly->p[i + 1].y;
- d = dist_ps(&(circle->center), &seg);
+ d = *dist_ps(&(circle->center), &seg);
#ifdef GEODEBUG
- printf("dist_cpoly- segment %d distance is %f\n", (i + 1), *d);
+ printf("dist_cpoly- segment %d distance is %f\n", (i + 1), d);
#endif
- if (*d < *result)
- *result = *d;
- pfree(d);
+ if (d < result)
+ result = d;
}
- *result -= circle->radius;
- if (*result < 0)
- *result = 0;
+ result -= circle->radius;
+ if (result < 0)
+ result = 0;
- return result;
-} /* dist_cpoly() */
+ PG_RETURN_FLOAT8(result);
+}
/*---------------------------------------------------------------------
@@ -2728,19 +2688,18 @@ on_pb(Point *pt, BOX *box)
* but not cross.
* (we can do p-in-p in lg(n), but it takes preprocessing)
*/
-#define NEXT(A) ((A+1) % path->npts) /* cyclic "i+1" */
+#define NEXT(A) (((A)+1) % path->npts) /* cyclic "i+1" */
-bool
-on_ppath(Point *pt, PATH *path)
+Datum
+on_ppath(PG_FUNCTION_ARGS)
{
+ Point *pt = PG_GETARG_POINT_P(0);
+ PATH *path = PG_GETARG_PATH_P(1);
int i,
n;
double a,
b;
- if (!PointerIsValid(pt) || !PointerIsValid(path))
- return FALSE;
-
/*-- OPEN --*/
if (!path->closed)
{
@@ -2751,15 +2710,15 @@ on_ppath(Point *pt, PATH *path)
b = point_dt(pt, &path->p[i + 1]);
if (FPeq(a + b,
point_dt(&path->p[i], &path->p[i + 1])))
- return TRUE;
+ PG_RETURN_BOOL(true);
a = b;
}
- return FALSE;
+ PG_RETURN_BOOL(false);
}
/*-- CLOSED --*/
- return point_inside(pt, path->npts, path->p);
-} /* on_ppath() */
+ PG_RETURN_BOOL(point_inside(pt, path->npts, path->p) != 0);
+}
bool
@@ -2951,23 +2910,21 @@ make_bound_box(POLYGON *poly)
* "x0,y0,...,xn,yn"
* also supports the older style "(x1,...,xn,y1,...yn)"
*------------------------------------------------------------------*/
-POLYGON *
-poly_in(char *str)
+Datum
+poly_in(PG_FUNCTION_ARGS)
{
+ char *str = PG_GETARG_CSTRING(0);
POLYGON *poly;
int npts;
int size;
int isopen;
char *s;
- if (!PointerIsValid(str))
- elog(ERROR, " Bad (null) polygon external representation");
-
if ((npts = pair_count(str, ',')) <= 0)
elog(ERROR, "Bad polygon external representation '%s'", str);
- size = offsetof(POLYGON, p[0]) +(sizeof(poly->p[0]) * npts);
- poly = palloc(size);
+ size = offsetof(POLYGON, p[0]) + sizeof(poly->p[0]) * npts;
+ poly = (POLYGON *) palloc(size);
MemSet((char *) poly, 0, size); /* zero any holes */
poly->size = size;
@@ -2979,22 +2936,20 @@ poly_in(char *str)
make_bound_box(poly);
- return poly;
-} /* poly_in() */
+ PG_RETURN_POLYGON_P(poly);
+}
/*---------------------------------------------------------------
* poly_out - convert internal POLYGON representation to the
* character string format "((f8,f8),...,(f8,f8))"
- * also support old format "(f8,f8,...,f8,f8)"
*---------------------------------------------------------------*/
-char *
-poly_out(POLYGON *poly)
+Datum
+poly_out(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(poly))
- return NULL;
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
- return path_encode(TRUE, poly->npts, &(poly->p[0]));
-} /* poly_out() */
+ PG_RETURN_CSTRING(path_encode(TRUE, poly->npts, poly->p));
+}
/*-------------------------------------------------------
@@ -3002,10 +2957,13 @@ poly_out(POLYGON *poly)
* the right most point of A left of the left most point
* of B?
*-------------------------------------------------------*/
-bool
-poly_left(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_left(PG_FUNCTION_ARGS)
{
- return polya->boundbox.high.x < polyb->boundbox.low.x;
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
+
+ PG_RETURN_BOOL(polya->boundbox.high.x < polyb->boundbox.low.x);
}
/*-------------------------------------------------------
@@ -3013,10 +2971,13 @@ poly_left(POLYGON *polya, POLYGON *polyb)
* the left most point of A left of the right most point
* of B?
*-------------------------------------------------------*/
-bool
-poly_overleft(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_overleft(PG_FUNCTION_ARGS)
{
- return polya->boundbox.low.x <= polyb->boundbox.high.x;
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
+
+ PG_RETURN_BOOL(polya->boundbox.low.x <= polyb->boundbox.high.x);
}
/*-------------------------------------------------------
@@ -3024,10 +2985,13 @@ poly_overleft(POLYGON *polya, POLYGON *polyb)
* the left most point of A right of the right most point
* of B?
*-------------------------------------------------------*/
-bool
-poly_right(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_right(PG_FUNCTION_ARGS)
{
- return polya->boundbox.low.x > polyb->boundbox.high.x;
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
+
+ PG_RETURN_BOOL(polya->boundbox.low.x > polyb->boundbox.high.x);
}
/*-------------------------------------------------------
@@ -3035,10 +2999,13 @@ poly_right(POLYGON *polya, POLYGON *polyb)
* the right most point of A right of the left most point
* of B?
*-------------------------------------------------------*/
-bool
-poly_overright(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_overright(PG_FUNCTION_ARGS)
{
- return polya->boundbox.high.x > polyb->boundbox.low.x;
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
+
+ PG_RETURN_BOOL(polya->boundbox.high.x > polyb->boundbox.low.x);
}
/*-------------------------------------------------------
@@ -3048,60 +3015,47 @@ poly_overright(POLYGON *polya, POLYGON *polyb)
* direction since polygons are non-directional and are
* closed shapes.
*-------------------------------------------------------*/
-bool
-poly_same(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_same(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(polya) || !PointerIsValid(polyb))
- return FALSE;
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
if (polya->npts != polyb->npts)
- return FALSE;
-
- return plist_same(polya->npts, polya->p, polyb->p);
+ PG_RETURN_BOOL(false);
-#ifdef NOT_USED
- for (i = 0; i < polya->npts; i++)
- {
- if ((polya->p[i].x != polyb->p[i].x)
- || (polya->p[i].y != polyb->p[i].y))
- return FALSE;
- }
- return TRUE;
-#endif
-} /* poly_same() */
+ PG_RETURN_BOOL(plist_same(polya->npts, polya->p, polyb->p));
+}
/*-----------------------------------------------------------------
* Determine if polygon A overlaps polygon B by determining if
* their bounding boxes overlap.
+ *
+ * XXX ought to do a more correct check?
*-----------------------------------------------------------------*/
-bool
-poly_overlap(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_overlap(PG_FUNCTION_ARGS)
{
- return box_overlap(&(polya->boundbox), &(polyb->boundbox));
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
+
+ PG_RETURN_BOOL(box_overlap(&(polya->boundbox), &(polyb->boundbox)));
}
/*-----------------------------------------------------------------
- * Determine if polygon A contains polygon B by determining if A's
- * bounding box contains B's bounding box.
+ * Determine if polygon A contains polygon B.
*-----------------------------------------------------------------*/
-#ifdef NOT_USED
-bool
-poly_contain(POLYGON *polya, POLYGON *polyb)
-{
- return box_contain(&(polya->boundbox), &(polyb->boundbox));
-}
-
-#endif
-
-bool
-poly_contain(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_contain(PG_FUNCTION_ARGS)
{
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
int i;
- if (!PointerIsValid(polya) || !PointerIsValid(polyb))
- return FALSE;
-
+ /*
+ * Quick check to see if bounding box is contained.
+ */
if (box_contain(&(polya->boundbox), &(polyb->boundbox)))
{
for (i = 0; i < polyb->npts; i++)
@@ -3111,7 +3065,7 @@ poly_contain(POLYGON *polya, POLYGON *polyb)
#if GEODEBUG
printf("poly_contain- point (%f,%f) not in polygon\n", polyb->p[i].x, polyb->p[i].y);
#endif
- return FALSE;
+ PG_RETURN_BOOL(false);
}
}
for (i = 0; i < polya->npts; i++)
@@ -3121,38 +3075,33 @@ poly_contain(POLYGON *polya, POLYGON *polyb)
#if GEODEBUG
printf("poly_contain- point (%f,%f) in polygon\n", polya->p[i].x, polya->p[i].y);
#endif
- return FALSE;
+ PG_RETURN_BOOL(false);
}
}
- return TRUE;
+ PG_RETURN_BOOL(true);
}
+
#if GEODEBUG
printf("poly_contain- bound box ((%f,%f),(%f,%f)) not inside ((%f,%f),(%f,%f))\n",
polyb->boundbox.low.x, polyb->boundbox.low.y, polyb->boundbox.high.x, polyb->boundbox.high.y,
polya->boundbox.low.x, polya->boundbox.low.y, polya->boundbox.high.x, polya->boundbox.high.y);
#endif
- return FALSE;
-} /* poly_contain() */
+ PG_RETURN_BOOL(false);
+}
/*-----------------------------------------------------------------
* Determine if polygon A is contained by polygon B by determining
* if A's bounding box is contained by B's bounding box.
*-----------------------------------------------------------------*/
-#ifdef NOT_USED
-bool
-poly_contained(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_contained(PG_FUNCTION_ARGS)
{
- return box_contained(&(polya->boundbox), &(polyb->boundbox));
-}
-
-#endif
+ Datum polya = PG_GETARG_DATUM(0);
+ Datum polyb = PG_GETARG_DATUM(1);
-bool
-poly_contained(POLYGON *polya, POLYGON *polyb)
-{
- return poly_contain(polyb, polya);
-} /* poly_contained() */
+ PG_RETURN_DATUM(DirectFunctionCall2(poly_contain, polyb, polya));
+}
/* poly_contain_pt()
@@ -3165,39 +3114,37 @@ poly_contained(POLYGON *polya, POLYGON *polyb)
* (code offered for use by J. Franks in Linux Journal letter.)
*/
-bool
-poly_contain_pt(POLYGON *poly, Point *p)
+Datum
+poly_contain_pt(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(poly) || !PointerIsValid(p))
- return FALSE;
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
+ Point *p = PG_GETARG_POINT_P(1);
- return point_inside(p, poly->npts, &(poly->p[0])) != 0;
-} /* poly_contain_pt() */
+ PG_RETURN_BOOL(point_inside(p, poly->npts, poly->p) != 0);
+}
-bool
-pt_contained_poly(Point *p, POLYGON *poly)
+Datum
+pt_contained_poly(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(p) || !PointerIsValid(poly))
- return FALSE;
+ Point *p = PG_GETARG_POINT_P(0);
+ POLYGON *poly = PG_GETARG_POLYGON_P(1);
- return poly_contain_pt(poly, p);
-} /* pt_contained_poly() */
+ PG_RETURN_BOOL(point_inside(p, poly->npts, poly->p) != 0);
+}
-double *
-poly_distance(POLYGON *polya, POLYGON *polyb)
+Datum
+poly_distance(PG_FUNCTION_ARGS)
{
- double *result;
-
- if (!PointerIsValid(polya) || !PointerIsValid(polyb))
- return NULL;
-
- result = palloc(sizeof(double));
+#ifdef NOT_USED
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
+#endif
- *result = 0;
+ elog(ERROR, "poly_distance not implemented");
- return result;
-} /* poly_distance() */
+ PG_RETURN_NULL();
+}
/***********************************************************************
@@ -3384,19 +3331,20 @@ box_div(BOX *box, Point *p)
/* path_add()
* Concatenate two paths (only if they are both open).
*/
-PATH *
-path_add(PATH *p1, PATH *p2)
+Datum
+path_add(PG_FUNCTION_ARGS)
{
+ PATH *p1 = PG_GETARG_PATH_P(0);
+ PATH *p2 = PG_GETARG_PATH_P(1);
PATH *result;
int size;
int i;
- if (!(PointerIsValid(p1) && PointerIsValid(p2))
- || p1->closed || p2->closed)
- return NULL;
+ if (p1->closed || p2->closed)
+ PG_RETURN_NULL();
- size = offsetof(PATH, p[0]) +(sizeof(p1->p[0]) * (p1->npts + p2->npts));
- result = palloc(size);
+ size = offsetof(PATH, p[0]) + sizeof(p1->p[0]) * (p1->npts + p2->npts);
+ result = (PATH *) palloc(size);
result->size = size;
result->npts = (p1->npts + p2->npts);
@@ -3413,134 +3361,112 @@ path_add(PATH *p1, PATH *p2)
result->p[i + p1->npts].y = p2->p[i].y;
}
- return result;
-} /* path_add() */
+ PG_RETURN_PATH_P(result);
+}
/* path_add_pt()
- * Translation operator.
+ * Translation operators.
*/
-PATH *
-path_add_pt(PATH *path, Point *point)
+Datum
+path_add_pt(PG_FUNCTION_ARGS)
{
- PATH *result;
+ PATH *path = PG_GETARG_PATH_P_COPY(0);
+ Point *point = PG_GETARG_POINT_P(1);
int i;
- if ((!PointerIsValid(path)) || (!PointerIsValid(point)))
- return NULL;
-
- result = path_copy(path);
-
for (i = 0; i < path->npts; i++)
{
- result->p[i].x += point->x;
- result->p[i].y += point->y;
+ path->p[i].x += point->x;
+ path->p[i].y += point->y;
}
- return result;
-} /* path_add_pt() */
+ PG_RETURN_PATH_P(path);
+}
-PATH *
-path_sub_pt(PATH *path, Point *point)
+Datum
+path_sub_pt(PG_FUNCTION_ARGS)
{
- PATH *result;
+ PATH *path = PG_GETARG_PATH_P_COPY(0);
+ Point *point = PG_GETARG_POINT_P(1);
int i;
- if ((!PointerIsValid(path)) || (!PointerIsValid(point)))
- return NULL;
-
- result = path_copy(path);
-
for (i = 0; i < path->npts; i++)
{
- result->p[i].x -= point->x;
- result->p[i].y -= point->y;
+ path->p[i].x -= point->x;
+ path->p[i].y -= point->y;
}
- return result;
-} /* path_sub_pt() */
-
+ PG_RETURN_PATH_P(path);
+}
/* path_mul_pt()
* Rotation and scaling operators.
*/
-PATH *
-path_mul_pt(PATH *path, Point *point)
+Datum
+path_mul_pt(PG_FUNCTION_ARGS)
{
- PATH *result;
+ PATH *path = PG_GETARG_PATH_P_COPY(0);
+ Point *point = PG_GETARG_POINT_P(1);
Point *p;
int i;
- if ((!PointerIsValid(path)) || (!PointerIsValid(point)))
- return NULL;
-
- result = path_copy(path);
-
for (i = 0; i < path->npts; i++)
{
p = point_mul(&path->p[i], point);
- result->p[i].x = p->x;
- result->p[i].y = p->y;
+ path->p[i].x = p->x;
+ path->p[i].y = p->y;
pfree(p);
}
- return result;
-} /* path_mul_pt() */
+ PG_RETURN_PATH_P(path);
+}
-PATH *
-path_div_pt(PATH *path, Point *point)
+Datum
+path_div_pt(PG_FUNCTION_ARGS)
{
- PATH *result;
+ PATH *path = PG_GETARG_PATH_P_COPY(0);
+ Point *point = PG_GETARG_POINT_P(1);
Point *p;
int i;
- if ((!PointerIsValid(path)) || (!PointerIsValid(point)))
- return NULL;
-
- result = path_copy(path);
-
for (i = 0; i < path->npts; i++)
{
p = point_div(&path->p[i], point);
- result->p[i].x = p->x;
- result->p[i].y = p->y;
+ path->p[i].x = p->x;
+ path->p[i].y = p->y;
pfree(p);
}
- return result;
-} /* path_div_pt() */
+ PG_RETURN_PATH_P(path);
+}
-Point *
-path_center(PATH *path)
+Datum
+path_center(PG_FUNCTION_ARGS)
{
- Point *result;
-
- if (!PointerIsValid(path))
- return NULL;
+#ifdef NOT_USED
+ PATH *path = PG_GETARG_PATH_P(0);
+#endif
elog(ERROR, "path_center not implemented");
- result = palloc(sizeof(Point));
- result = NULL;
-
- return result;
-} /* path_center() */
+ PG_RETURN_NULL();
+}
-POLYGON *
-path_poly(PATH *path)
+Datum
+path_poly(PG_FUNCTION_ARGS)
{
+ PATH *path = PG_GETARG_PATH_P(0);
POLYGON *poly;
int size;
int i;
- if (!PointerIsValid(path))
- return NULL;
-
+ /* This is not very consistent --- other similar cases return NULL ... */
if (!path->closed)
elog(ERROR, "Open path cannot be converted to polygon");
- size = offsetof(POLYGON, p[0]) +(sizeof(poly->p[0]) * path->npts);
- poly = palloc(size);
+ size = offsetof(POLYGON, p[0]) + sizeof(poly->p[0]) * path->npts;
+ poly = (POLYGON *) palloc(size);
poly->size = size;
poly->npts = path->npts;
@@ -3553,57 +3479,8 @@ path_poly(PATH *path)
make_bound_box(poly);
- return poly;
-} /* path_polygon() */
-
-
-/* upgradepath()
- * Convert path read from old-style string into correct representation.
- *
- * Old-style: '(closed,#pts,x1,y1,...)' where closed is a boolean flag
- * New-style: '((x1,y1),...)' for closed path
- * '[(x1,y1),...]' for open path
- */
-PATH *
-upgradepath(PATH *path)
-{
- PATH *result;
- int size,
- npts;
- int i;
-
- if (!PointerIsValid(path) || (path->npts < 2))
- return NULL;
-
- if (!isoldpath(path))
- elog(ERROR, "upgradepath: path already upgraded?");
-
- npts = (path->npts - 1);
- size = offsetof(PATH, p[0]) +(sizeof(path->p[0]) * npts);
- result = palloc(size);
- MemSet((char *) result, 0, size);
-
- result->size = size;
- result->npts = npts;
- result->closed = (path->p[0].x != 0);
-
- for (i = 0; i < result->npts; i++)
- {
- result->p[i].x = path->p[i + 1].x;
- result->p[i].y = path->p[i + 1].y;
- }
-
- return result;
-} /* upgradepath() */
-
-bool
-isoldpath(PATH *path)
-{
- if (!PointerIsValid(path) || (path->npts < 2))
- return FALSE;
-
- return path->npts == (path->p[0].y + 1);
-} /* isoldpath() */
+ PG_RETURN_POLYGON_P(poly);
+}
/***********************************************************************
@@ -3612,67 +3489,64 @@ isoldpath(PATH *path)
**
***********************************************************************/
-int4
-poly_npoints(POLYGON *poly)
+Datum
+poly_npoints(PG_FUNCTION_ARGS)
{
- if (!PointerIsValid(poly))
- return FALSE;
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
- return poly->npts;
-} /* poly_npoints() */
+ PG_RETURN_INT32(poly->npts);
+}
-Point *
-poly_center(POLYGON *poly)
+Datum
+poly_center(PG_FUNCTION_ARGS)
{
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
Point *result;
CIRCLE *circle;
- if (!PointerIsValid(poly))
- return NULL;
-
- if (PointerIsValid(circle = poly_circle(poly)))
+ circle = DatumGetCircleP(DirectFunctionCall1(poly_circle,
+ PolygonPGetDatum(poly)));
+ if (PointerIsValid(circle))
{
result = circle_center(circle);
pfree(circle);
-
}
else
- result = NULL;
+ PG_RETURN_NULL();
- return result;
-} /* poly_center() */
+ PG_RETURN_POINT_P(result);
+}
-BOX *
-poly_box(POLYGON *poly)
+Datum
+poly_box(PG_FUNCTION_ARGS)
{
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
BOX *box;
- if (!PointerIsValid(poly) || (poly->npts < 1))
- return NULL;
+ if (poly->npts < 1)
+ PG_RETURN_NULL();
box = box_copy(&poly->boundbox);
- return box;
-} /* poly_box() */
+ PG_RETURN_BOX_P(box);
+}
/* box_poly()
* Convert a box to a polygon.
*/
-POLYGON *
-box_poly(BOX *box)
+Datum
+box_poly(PG_FUNCTION_ARGS)
{
+ BOX *box = PG_GETARG_BOX_P(0);
POLYGON *poly;
int size;
- if (!PointerIsValid(box))
- return NULL;
-
/* map four corners of the box to a polygon */
- size = offsetof(POLYGON, p[0]) +(sizeof(poly->p[0]) * 4);
- poly = palloc(size);
+ size = offsetof(POLYGON, p[0]) + sizeof(poly->p[0]) * 4;
+ poly = (POLYGON *) palloc(size);
poly->size = size;
poly->npts = 4;
@@ -3686,24 +3560,23 @@ box_poly(BOX *box)
poly->p[3].x = box->high.x;
poly->p[3].y = box->low.y;
- box_fill(&poly->boundbox, box->high.x, box->low.x, box->high.y, box->low.y);
+ box_fill(&poly->boundbox, box->high.x, box->low.x,
+ box->high.y, box->low.y);
- return poly;
-} /* box_poly() */
+ PG_RETURN_POLYGON_P(poly);
+}
-PATH *
-poly_path(POLYGON *poly)
+Datum
+poly_path(PG_FUNCTION_ARGS)
{
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
PATH *path;
int size;
int i;
- if (!PointerIsValid(poly) || (poly->npts < 0))
- return NULL;
-
- size = offsetof(PATH, p[0]) +(sizeof(path->p[0]) * poly->npts);
- path = palloc(size);
+ size = offsetof(PATH, p[0]) + sizeof(path->p[0]) * poly->npts;
+ path = (PATH *) palloc(size);
path->size = size;
path->npts = poly->npts;
@@ -3715,103 +3588,8 @@ poly_path(POLYGON *poly)
path->p[i].y = poly->p[i].y;
}
- return path;
-} /* poly_path() */
-
-
-/* upgradepoly()
- * Convert polygon read as pre-v6.1 string to new interpretation.
- * Old-style: '(x1,x2,...,y1,y2,...)'
- * New-style: '(x1,y1,x2,y2,...)'
- */
-POLYGON *
-upgradepoly(POLYGON *poly)
-{
- POLYGON *result;
- int size;
- int n2,
- i,
- ii;
-
- if (!PointerIsValid(poly) || (poly->npts < 1))
- return NULL;
-
- size = offsetof(POLYGON, p[0]) +(sizeof(poly->p[0]) * poly->npts);
- result = palloc(size);
- MemSet((char *) result, 0, size);
-
- result->size = size;
- result->npts = poly->npts;
-
- n2 = poly->npts / 2;
-
- for (i = 0; i < n2; i++)
- {
- result->p[2 * i].x = poly->p[i].x; /* even indices */
- result->p[2 * i + 1].x = poly->p[i].y; /* odd indices */
- }
-
- if ((ii = ((poly->npts % 2) ? 1 : 0)))
- {
- result->p[poly->npts - 1].x = poly->p[n2].x;
- result->p[0].y = poly->p[n2].y;
- }
-
- for (i = 0; i < n2; i++)
- {
- result->p[2 * i + ii].y = poly->p[i + n2 + ii].x; /* even (+offset)
- * indices */
- result->p[2 * i + ii + 1].y = poly->p[i + n2 + ii].y; /* odd (+offset) indices */
- }
-
- return result;
-} /* upgradepoly() */
-
-/* revertpoly()
- * Reverse effect of upgradepoly().
- */
-POLYGON *
-revertpoly(POLYGON *poly)
-{
- POLYGON *result;
- int size;
- int n2,
- i,
- ii;
-
- if (!PointerIsValid(poly) || (poly->npts < 1))
- return NULL;
-
- size = offsetof(POLYGON, p[0]) +(sizeof(poly->p[0]) * poly->npts);
- result = palloc(size);
- MemSet((char *) result, 0, size);
-
- result->size = size;
- result->npts = poly->npts;
-
- n2 = poly->npts / 2;
-
- for (i = 0; i < n2; i++)
- {
- result->p[i].x = poly->p[2 * i].x; /* even indices */
- result->p[i].y = poly->p[2 * i + 1].x; /* odd indices */
- }
-
- if ((ii = ((poly->npts % 2) ? 1 : 0)))
- {
- result->p[n2].x = poly->p[poly->npts - 1].x;
- result->p[n2].y = poly->p[0].y;
- }
-
- for (i = 0; i < n2; i++)
- {
- result->p[i + n2 + ii].x = poly->p[2 * i + ii].y; /* even (+offset)
- * indices */
- result->p[i + n2 + ii].y = poly->p[2 * i + ii + 1].y; /* odd (+offset) indices */
- }
-
- return result;
-} /* revertpoly() */
+ PG_RETURN_PATH_P(path);
+}
/***********************************************************************
@@ -4398,19 +4176,17 @@ circle_poly(PG_FUNCTION_ARGS)
* XXX This algorithm should use weighted means of line segments
* rather than straight average values of points - tgl 97/01/21.
*/
-CIRCLE *
-poly_circle(POLYGON *poly)
+Datum
+poly_circle(PG_FUNCTION_ARGS)
{
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
CIRCLE *circle;
int i;
- if (!PointerIsValid(poly))
- return NULL;
-
if (poly->npts < 2)
elog(ERROR, "Unable to convert polygon to circle");
- circle = palloc(sizeof(CIRCLE));
+ circle = (CIRCLE *) palloc(sizeof(CIRCLE));
circle->center.x = 0;
circle->center.y = 0;
@@ -4431,8 +4207,8 @@ poly_circle(POLYGON *poly)
if (FPzero(circle->radius))
elog(ERROR, "Unable to convert polygon to circle");
- return circle;
-} /* poly_circle() */
+ PG_RETURN_CIRCLE_P(circle);
+}
/***********************************************************************
@@ -4450,7 +4226,6 @@ point_inside(Point *p, int npts, Point *plist)
y0;
double px,
py;
-
int i;
double x,
y;
@@ -4494,7 +4269,7 @@ point_inside(Point *p, int npts, Point *plist)
if (crossnum != 0)
return 1;
return 0;
-} /* point_inside() */
+}
/* lseg_crossing()