]> granicus.if.org Git - postgresql/commitdiff
Major patch from Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
authorMarc G. Fournier <scrappy@hub.org>
Tue, 22 Apr 1997 17:35:09 +0000 (17:35 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Tue, 22 Apr 1997 17:35:09 +0000 (17:35 +0000)
OK, here are a passel of patches for the geometric data types.
These add a "circle" data type, new operators and functions
for the existing data types, and change the default formats
for some of the existing types to make them consistant with
each other. Current formatting conventions (e.g. compatible
with v6.0 to allow dump/reload) are supported, but the new
conventions should be an improvement and we can eventually
drop the old conventions entirely.

For example, there are two kinds of paths (connected line segments),
open and closed, and the old format was

'(1,2,1,2,3,4)' for a closed path with two points (1,2) and (3,4)
'(0,2,1,2,3,4)' for an open path with two points (1,2) and (3,4)

Pretty arcane, huh? The new format for paths is

'((1,2),(3,4))' for a closed path with two points (1,2) and (3,4)
'[(1,2),(3,4)]' for an open path with two points (1,2) and (3,4)

For polygons, the old convention is

'(0,4,2,0,4,3)' for a triangle with points at (0,0),(4,4), and (2,3)

and the new convention is

'((0,0),(4,4),(2,3))' for a triangle with points at (0,0),(4,4), and (2,3)

Other data types which are also represented as lists of points
(e.g. boxes, line segments, and polygons) have similar representations
(they surround each point with parens).

For v6.1, any format which can be interpreted as the old style format
is decoded as such; we can remove that backwards compatibility but ugly
convention for v7.0. This will allow dump/reloads from v6.0.

These include some updates to the regression test files to change the test
for creating a data type from "circle" to "widget" to keep the test from
trashing the new builtin circle type.

13 files changed:
src/backend/access/rtree/rtproc.c
src/backend/utils/adt/geo_ops.c
src/include/catalog/pg_operator.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_type.h
src/include/utils/geo_decls.h
src/test/regress/expected/create_operator.out
src/test/regress/expected/create_type.out
src/test/regress/expected/misc.out
src/test/regress/input/create_function.source
src/test/regress/regress.c
src/test/regress/sql/create_operator.sql
src/test/regress/sql/create_type.sql

index 932feec0b391e8c86e6fad62a9d329c5a250e570..ac7a3abfecfb8d591981b6f512300fa0c19e6269 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.6 1997/03/14 23:17:41 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.7 1997/04/22 17:31:23 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,10 +30,10 @@ BOX
     if ((n = (BOX *) palloc(sizeof (*n))) == (BOX *) NULL)
        elog(WARN, "Cannot allocate box for union");
     
-    n->xh = Max(a->xh, b->xh);
-    n->yh = Max(a->yh, b->yh);
-    n->xl = Min(a->xl, b->xl);
-    n->yl = Min(a->yl, b->yl);
+    n->high.x = Max(a->high.x, b->high.x);
+    n->high.y = Max(a->high.y, b->high.y);
+    n->low.x = Min(a->low.x, b->low.x);
+    n->low.y = Min(a->low.y, b->low.y);
     
     return (n);
 }
@@ -46,12 +46,12 @@ rt_box_inter(BOX *a, BOX *b)
     if ((n = (BOX *) palloc(sizeof (*n))) == (BOX *) NULL)
        elog(WARN, "Cannot allocate box for union");
     
-    n->xh = Min(a->xh, b->xh);
-    n->yh = Min(a->yh, b->yh);
-    n->xl = Max(a->xl, b->xl);
-    n->yl = Max(a->yl, b->yl);
+    n->high.x = Min(a->high.x, b->high.x);
+    n->high.y = Min(a->high.y, b->high.y);
+    n->low.x = Max(a->low.x, b->low.x);
+    n->low.y = Max(a->low.y, b->low.y);
     
-    if (n->xh < n->xl || n->yh < n->yl) {
+    if (n->high.x < n->low.x || n->high.y < n->low.y) {
        pfree(n);
        return ((BOX *) NULL);
     }
@@ -62,10 +62,10 @@ rt_box_inter(BOX *a, BOX *b)
 void
 rt_box_size(BOX *a, float *size)
 {
-    if (a == (BOX *) NULL || a->xh <= a->xl || a->yh <= a->yl)
+    if (a == (BOX *) NULL || a->high.x <= a->low.x || a->high.y <= a->low.y)
        *size = 0.0;
     else
-       *size = (float) ((a->xh - a->xl) * (a->yh - a->yl));
+       *size = (float) ((a->high.x - a->low.x) * (a->high.y - a->low.y));
     
     return;
 }
@@ -97,10 +97,10 @@ rt_poly_union(POLYGON *a, POLYGON *b)
     memset((char *) p, 0, sizeof(POLYGON));    /* zero any holes */
     p->size = sizeof(POLYGON);
     p->npts = 0;
-    p->boundbox.xh = Max(a->boundbox.xh, b->boundbox.xh);
-    p->boundbox.yh = Max(a->boundbox.yh, b->boundbox.yh);
-    p->boundbox.xl = Min(a->boundbox.xl, b->boundbox.xl);
-    p->boundbox.yl = Min(a->boundbox.yl, b->boundbox.yl);
+    p->boundbox.high.x = Max(a->boundbox.high.x, b->boundbox.high.x);
+    p->boundbox.high.y = Max(a->boundbox.high.y, b->boundbox.high.y);
+    p->boundbox.low.x = Min(a->boundbox.low.x, b->boundbox.low.x);
+    p->boundbox.low.y = Min(a->boundbox.low.y, b->boundbox.low.y);
     return p;
 }
 
@@ -111,12 +111,12 @@ rt_poly_size(POLYGON *a, float *size)
     
     size = (float *) palloc(sizeof(float));
     if (a == (POLYGON *) NULL || 
-       a->boundbox.xh <= a->boundbox.xl || 
-       a->boundbox.yh <= a->boundbox.yl)
+       a->boundbox.high.x <= a->boundbox.low.x || 
+       a->boundbox.high.y <= a->boundbox.low.y)
        *size = 0.0;
     else {
-       xdim = (a->boundbox.xh - a->boundbox.xl);
-       ydim = (a->boundbox.yh - a->boundbox.yl);
+       xdim = (a->boundbox.high.x - a->boundbox.low.x);
+       ydim = (a->boundbox.high.y - a->boundbox.low.y);
        
        *size = (float) (xdim * ydim);
     }
@@ -137,12 +137,12 @@ rt_poly_inter(POLYGON *a, POLYGON *b)
     memset((char *) p, 0, sizeof(POLYGON));    /* zero any holes */
     p->size = sizeof(POLYGON);
     p->npts = 0;
-    p->boundbox.xh = Min(a->boundbox.xh, b->boundbox.xh);
-    p->boundbox.yh = Min(a->boundbox.yh, b->boundbox.yh);
-    p->boundbox.xl = Max(a->boundbox.xl, b->boundbox.xl);
-    p->boundbox.yl = Max(a->boundbox.yl, b->boundbox.yl);
+    p->boundbox.high.x = Min(a->boundbox.high.x, b->boundbox.high.x);
+    p->boundbox.high.y = Min(a->boundbox.high.y, b->boundbox.high.y);
+    p->boundbox.low.x = Max(a->boundbox.low.x, b->boundbox.low.x);
+    p->boundbox.low.y = Max(a->boundbox.low.y, b->boundbox.low.y);
     
-    if (p->boundbox.xh < p->boundbox.xl || p->boundbox.yh < p->boundbox.yl)
+    if (p->boundbox.high.x < p->boundbox.low.x || p->boundbox.high.y < p->boundbox.low.y)
        {
            pfree(p);
            return ((POLYGON *) NULL);
index 32d8d6358ec0cad25bd6eaa0e100cdd083ffb4f4..4dacd09f1c6c5bd5104caa97522142c5fdfd22ce 100644 (file)
 /*-------------------------------------------------------------------------
  *
- * geo-ops.c--
+ * geo_ops.c--
  *    2D geometric operations
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.2 1997/03/14 23:20:15 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.3 1997/04/22 17:31:32 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <math.h>
-#include <float.h>     /* faked on sunos */
+#include <float.h>
 #include <stdio.h>     /* for sprintf proto, etc. */
+#include <stdlib.h>    /* for strtod, etc. */
 #include <string.h>
+#include <ctype.h>
 
 #include "postgres.h"
 
 #include "utils/geo_decls.h"
 #include "utils/palloc.h"
 
+#define OLD_FORMAT_IN  1
+#define OLD_FORMAT_OUT 0
+
+/*
+ * Delimiters for input and output strings.
+ * LDELIM, RDELIM, and DELIM are left, right, and separator delimiters, respectively.
+ * LDELIM_EP, RDELIM_EP are left and right delimiters for paths with endpoints.
+ */
+
 #define LDELIM         '('
 #define RDELIM         ')'
 #define        DELIM           ','
-#define BOXNARGS       4
-#define        LSEGNARGS       4
-#define        POINTNARGS      2
+#define LDELIM_EP      '['
+#define RDELIM_EP      ']'
+#define LDELIM_C       '<'
+#define RDELIM_C       '>'
+
+/* Maximum number of output digits printed */
+#define P_MAXDIG DBL_DIG
+#define P_MAXLEN (2*(P_MAXDIG+7)+1)
+
+static int digits8 = P_MAXDIG;
+
+int geo_precision(int digits);
+
+int geo_precision(int digits)
+{
+    if (digits > P_MAXDIG) {
+       digits8 = P_MAXDIG;
+    } else if (digits > 0) {
+       digits8 = digits;
+    };
+    return digits8;
+}
+
+/*
+ * Geometric data types are composed of points.
+ * This code tries to support a common format throughout the data types,
+ *  to allow for more predictable usage and data type conversion.
+ * The fundamental unit is the point. Other units are line segments,
+ *  open paths, boxes, closed paths, and polygons (which should be considered
+ *  non-intersecting closed paths).
+ *
+ * Data representation is as follows:
+ *  point:             (x,y)
+ *  line segment:      [(x1,y1),(x2,y2)]
+ *  box:               (x1,y1),(x2,y2)
+ *  open path:         [(x1,y1),...,(xn,yn)]
+ *  closed path:       ((x1,y1),...,(xn,yn))
+ *  polygon:           ((x1,y1),...,(xn,yn))
+ *
+ * For boxes, the points are opposite corners with the first point at the top right.
+ * For closed paths and polygons, the points should be reordered to allow
+ *  fast and correct equality comparisons.
+ *
+ * XXX perhaps points in complex shapes should be reordered internally
+ *  to allow faster internal operations, but should keep track of input order
+ *  and restore that order for text output - tgl 97/01/16
+ */
+
+int pair_decode(char *str, float8 *x, float8 *y, char **s);
+int pair_encode(float8 x, float8 y, char *str);
+int pair_count(char *s, char delim);
+int path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p);
+
+char *path_encode( bool closed, int npts, Point *pt);
+
+int pair_decode(char *str, float8 *x, float8 *y, char **s)
+{
+    int has_delim;
+    char *cp;
+
+    if (!PointerIsValid((char *)str))
+       return(FALSE);
+
+    while (isspace( *str)) str++;
+    if ((has_delim = (*str == LDELIM))) str++;
+
+    while (isspace( *str)) str++;
+    *x = strtod( str, &cp);
+    if (cp <= str) return(FALSE);
+    while (isspace( *cp)) cp++;
+    if (*cp++ != DELIM) return(FALSE);
+    while (isspace( *cp)) cp++;
+    *y = strtod( cp, &str);
+    if (str <= cp) return(FALSE);
+    while (isspace( *str)) str++;
+    if (has_delim) {
+       if (*str != RDELIM) return(FALSE);
+       str++;
+       while (isspace( *str)) str++;
+    };
+    if (s != NULL) *s = str;
+
+    return(TRUE);
+}
+
+int pair_encode(float8 x, float8 y, char *str)
+{
+    (void) sprintf(str, "%.*g,%.*g", digits8, x, digits8, y);
+    return(TRUE);
+}
+
+int path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p)
+{
+    int depth = 0;
+    char *s, *cp;
+    int i;
+
+    s = str;
+    while (isspace( *s)) s++;
+    if ((*isopen = (*s == LDELIM_EP))) {
+       /* no open delimiter allowed? */
+       if (! opentype) return(FALSE);
+       depth++;
+       s++;
+       while (isspace( *s)) s++;
+
+    } else if (*s == LDELIM) {
+       cp = (s+1);
+       while (isspace( *cp)) cp++;
+       if (*cp == LDELIM) {
+           /* nested delimiters with only one point? */
+           if (npts <= 1) return(FALSE);
+           depth++;
+           s = cp;
+       } else if (strrchr( s, LDELIM) == s) {
+           depth++;
+           s = cp;
+       };
+    };
+
+    for (i = 0; i < npts; i++) {
+       if (! pair_decode( s, &(p->x), &(p->y), &s))
+           return(FALSE);
+
+       if (*s == DELIM) s++;
+       p++;
+    };
+
+    while (depth > 0) {
+       if ((*s == RDELIM)
+         || ((*s == RDELIM_EP) && (*isopen) && (depth == 1))) {
+           depth--;
+           s++;
+           while (isspace( *s)) s++;
+       } else {
+           return(FALSE);
+       };
+    };
+    *ss = s;
+
+    return(TRUE);
+} /* path_decode() */
+
+char *path_encode( bool closed, int npts, Point *pt)
+{
+    char *result;
+
+    char *cp;
+    int i;
+
+    if (!PointerIsValid(result = (char *)PALLOC(npts*(P_MAXLEN+3)+2)))
+       elog(WARN, "Memory allocation failed, can't output path", NULL);
+
+    cp = result;
+    switch (closed) {
+    case TRUE:
+       *cp++ = LDELIM;
+       break;
+    case FALSE:
+       *cp++ = LDELIM_EP;
+       break;
+    default:
+       break;
+    };
+
+    for (i = 0; i < npts; i++) {
+        *cp++ = LDELIM;
+       if (! pair_encode( pt->x, pt->y, cp))
+         elog (WARN, "Unable to format path", NULL);
+       cp += strlen(cp);
+       *cp++ = RDELIM;
+       *cp++ = DELIM;
+       pt++;
+    };
+    cp--;
+    switch (closed) {
+    case TRUE:
+       *cp++ = RDELIM;
+       break;
+    case FALSE:
+       *cp++ = RDELIM_EP;
+       break;
+    default:
+       break;
+    };
+    *cp = '\0';
+
+    return(result);
+} /* path_encode() */
+
+/*-------------------------------------------------------------
+ * pair_count - count the number of points
+ * allow the following notation:
+ * '((1,2),(3,4))'
+ * '(1,3,2,4)'
+ * require an odd number of delim characters in the string
+ *-------------------------------------------------------------*/
+int pair_count(char *s, char delim)
+{
+    int ndelim = 0;
+
+    while ((s = strchr( s, delim)) != NULL) {
+       ndelim++;
+       s++;
+    };
+    return((ndelim % 2)? ((ndelim+1)/2): -1);
+}
 
 /***********************************************************************
  **
 
 /*     box_in  -       convert a string to internal form.
  *
- *     str:    input string "(f8, f8, f8, f8)"
+ *     External format: (two corners of box)
+ *             "(f8, f8), (f8, f8)"
+ *             also supports the older style "(f8, f8, f8, f8)"
  */
 BOX *box_in(char *str)
 {
-    double     tmp;
-    char       *p, *coord[BOXNARGS];
-    int        i;
-    BOX        *result;
-    
-    if (str == NULL)
-       elog (WARN," Bad (null) box external representation");
-    
-    if ((p = (char *)strchr(str, LDELIM)) == (char *)NULL)
+    BOX        *box;
+
+    int isopen;
+    char *s;
+    double x, y;
+
+    if (!PointerIsValid((char *)str))
+       elog (WARN," Bad (null) box external representation",NULL);
+
+    if (!PointerIsValid(box = PALLOCTYPE(BOX)))
+      elog(WARN, "Memory allocation failed, can't input box '%s'",str);
+
+    if ((! path_decode(FALSE, 2, str, &isopen, &s, &(box->high)))
+      || (*s != '\0'))
        elog (WARN, "Bad box external representation '%s'",str);
-    for (i = 0, p = str; *p && i < BOXNARGS && *p != RDELIM; p++)
-       if (*p == DELIM || (*p == LDELIM && !i))
-           coord[i++] = p + 1;
-    if (i < BOXNARGS - 1)
-       elog (WARN, "Bad box external representation '%s'", str);
-    result = PALLOCTYPE(BOX);
-    result->xh = atof(coord[0]);
-    result->yh = atof(coord[1]);
-    result->xl = atof(coord[2]);
-    result->yl = atof(coord[3]);
-    if (result->xh < result->xl) {
-       tmp = result->xh;
-       result->xh = result->xl;
-       result->xl = tmp;
-    }
-    if (result->yh < result->yl) {
-       tmp = result->yh;
-       result->yh = result->yl;
-       result->yl = tmp;
-    }
-    
-    return(result);
+
+    /* reorder corners if necessary... */
+    if (box->high.x < box->low.x) {
+       x = box->high.x;
+       box->high.x = box->low.x;
+       box->low.x = x;
+    };
+    if (box->high.y < box->low.y) {
+       y = box->high.y;
+       box->high.y = box->low.y;
+       box->low.y = y;
+    };
+
+    return(box);
 }
 
 /*     box_out -       convert a box to external form.
  */
 char *box_out(BOX *box)
 {
-    char       *result;
-    
-    if (box == NULL)
+#if OLD_FORMAT_OUT
+    char *result;
+
+    char *cp;
+#endif
+
+    if (!PointerIsValid((char *)box))
        return(NULL);
-    result = (char *)PALLOC(80);
-    (void) sprintf(result, "(%G,%G,%G,%G)",
-                  box->xh, box->yh, box->xl, box->yl);
-    
-    return(result);
+
+#if OLD_FORMAT_OUT
+    if (!PointerIsValid(result = (char *)PALLOC(2*(P_MAXLEN+1)+2)))
+       elog(WARN, "Memory allocation failed, can't output box", NULL);
+
+    cp = result;
+    *cp++ = LDELIM;
+    if (! pair_encode( box->high.x, box->high.y, cp))
+         elog (WARN, "Unable to format box", NULL);
+    cp += strlen(cp);
+    *cp++ = DELIM;
+    if (! pair_encode( box->low.x, box->low.y, cp))
+         elog (WARN, "Unable to format box", NULL);
+    cp += strlen(cp);
+    *cp++ = RDELIM;
+    *cp = '\0';
+
+    return( result);
+#else
+    return( path_encode( -1, 2, (Point *) &(box->high)));
+#endif
 }
 
 
@@ -109,22 +343,20 @@ BOX *box_construct(double x1, double x2, double y1, double y2)
  */
 BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2)
 {
-    double     tmp;
-    
-    result->xh = x1;
-    result->xl = x2;
-    result->yh = y1;
-    result->yl = y2;
-    if (result->xh < result->xl) {
-       tmp = result->xh;
-       result->xh = result->xl;
-       result->xl = tmp;
-    }
-    if (result->yh < result->yl) {
-       tmp = result->yh;
-       result->yh = result->yl;
-       result->yl = tmp;
-    }
+    if (x1 > x2) {
+       result->high.x = x1;
+       result->low.x = x2;
+    } else {
+       result->high.x = x2;
+       result->low.x = x1;
+    };
+    if (y1 > y2) {
+       result->high.y = y1;
+       result->low.y = y2;
+    } else {
+       result->high.y = y2;
+       result->low.y = y1;
+    };
     
     return(result);
 }
@@ -150,20 +382,20 @@ BOX *box_copy(BOX *box)
 
 /*     box_same        -       are two boxes identical?
  */
-long box_same(BOX *box1, BOX *box2)
+bool box_same(BOX *box1, BOX *box2)
 {
-    return((box1->xh == box2->xh && box1->xl == box2->xl) &&
-          (box1->yh == box2->yh && box1->yl == box2->yl));
+    return((FPeq(box1->high.x,box2->high.x) && FPeq(box1->low.x,box2->low.x)) &&
+         (FPeq(box1->high.y,box2->high.y) && FPeq(box1->low.y,box2->low.y)));
 }
 
 /*     box_overlap     -       does box1 overlap box2?
  */
-long box_overlap(BOX *box1, BOX *box2)
+bool box_overlap(BOX *box1, BOX *box2)
 {
-    return(((box1->xh >= box2->xh && box1->xl <= box2->xh) ||
-           (box2->xh >= box1->xh && box2->xl <= box1->xh)) &&
-          ((box1->yh >= box2->yh && box1->yl <= box2->yh) ||
-           (box2->yh >= box1->yh && box2->yl <= box1->yh)) );
+    return(((FPge(box1->high.x,box2->high.x) && FPle(box1->low.x,box2->high.x)) ||
+           (FPge(box2->high.x,box1->high.x) && FPle(box2->low.x,box1->high.x))) &&
+          ((FPge(box1->high.y,box2->high.y) && FPle(box1->low.y,box2->high.y)) ||
+           (FPge(box2->high.y,box1->high.y) && FPle(box2->low.y,box1->high.y))) );
 }
 
 /*     box_overleft    -       is the right edge of box1 to the left of
@@ -172,23 +404,23 @@ long box_overlap(BOX *box1, BOX *box2)
  *     This is "less than or equal" for the end of a time range,
  *     when time ranges are stored as rectangles.
  */
-long box_overleft(BOX *box1, BOX *box2)
+bool box_overleft(BOX *box1, BOX *box2)
 {
-    return(box1->xh <= box2->xh);
+    return(FPle(box1->high.x,box2->high.x));
 }
 
 /*     box_left        -       is box1 strictly left of box2?
  */
-long box_left(BOX *box1, BOX *box2)
+bool box_left(BOX *box1, BOX *box2)
 {
-    return(box1->xh < box2->xl);
+    return(FPlt(box1->high.x,box2->low.x));
 }
 
 /*     box_right       -       is box1 strictly right of box2?
  */
-long box_right(BOX *box1, BOX *box2)
+bool box_right(BOX *box1, BOX *box2)
 {
-    return(box1->xl > box2->xh);
+    return(FPgt(box1->low.x,box2->high.x));
 }
 
 /*     box_overright   -       is the left edge of box1 to the right of
@@ -197,66 +429,66 @@ long box_right(BOX *box1, BOX *box2)
  *     This is "greater than or equal" for time ranges, when time ranges
  *     are stored as rectangles.
  */
-long box_overright(BOX *box1, BOX *box2)
+bool box_overright(BOX *box1, BOX *box2)
 {
-    return(box1->xl >= box2->xl);
+    return(box1->low.x >= box2->low.x);
 }
 
 /*     box_contained   -       is box1 contained by box2?
  */
-long box_contained(BOX *box1, BOX *box2)
+bool box_contained(BOX *box1, BOX *box2)
 {
-    return((box1->xh <= box2->xh && box1->xl >= box2->xl &&
-           box1->yh <= box2->yh && box1->yl >= box2->yl));
+    return((FPle(box1->high.x,box2->high.x) && FPge(box1->low.x,box2->low.x)) &&
+          (FPle(box1->high.y,box2->high.y) && FPge(box1->low.y,box2->low.y)));
 }
 
 /*     box_contain     -       does box1 contain box2?
  */
-long box_contain(BOX *box1, BOX *box2)
+bool box_contain(BOX *box1, BOX *box2)
 {
-    return((box1->xh >= box2->xh && box1->xl <= box2->xl &&
-           box1->yh >= box2->yh && box1->yl <= box2->yl));
+    return((FPge(box1->high.x,box2->high.x) && FPle(box1->low.x,box2->low.x) &&
+           FPge(box1->high.y,box2->high.y) && FPle(box1->low.y,box2->low.y)));
 }
 
 
 /*     box_positionop  -
- *             is box1 entirely {above, below } box2?
+ *             is box1 entirely {above,below} box2?
  */
-long box_below(BOX *box1, BOX *box2)
+bool box_below(BOX *box1, BOX *box2)
 {
-    return( box1->yh <= box2->yl );
+    return( FPle(box1->high.y,box2->low.y) );
 }
 
-long box_above(BOX *box1, BOX *box2)
+bool box_above(BOX *box1, BOX *box2)
 {
-    return( box1->yl >= box2->yh );
+    return( FPge(box1->low.y,box2->high.y) );
 }
 
 
 /*     box_relop       -       is area(box1) relop area(box2), within
  *                             our accuracy constraint?
  */
-long box_lt(BOX *box1, BOX *box2)
+bool box_lt(BOX *box1, BOX *box2)
 {
     return( FPlt(box_ar(box1), box_ar(box2)) );
 }
 
-long box_gt(BOX *box1, BOX *box2)
+bool box_gt(BOX *box1, BOX *box2)
 {
     return( FPgt(box_ar(box1), box_ar(box2)) );
 }
 
-long box_eq(BOX *box1, BOX *box2)
+bool box_eq(BOX *box1, BOX *box2)
 {
     return( FPeq(box_ar(box1), box_ar(box2)) );
 }
 
-long box_le(BOX        *box1, BOX *box2)
+bool box_le(BOX        *box1, BOX *box2)
 {
     return( FPle(box_ar(box1), box_ar(box2)) );
 }
 
-long box_ge(BOX        *box1, BOX *box2)
+bool box_ge(BOX        *box1, BOX *box2)
 {
     return( FPge(box_ar(box1), box_ar(box2)) );
 }
@@ -292,7 +524,7 @@ double *box_length(BOX *box)
     double     *result;
     
     result = PALLOCTYPE(double);
-    *result = box->xh - box->xl;
+    *result = box->high.x - box->low.x;
     
     return(result);
 }
@@ -306,7 +538,7 @@ double *box_height(BOX *box)
     double     *result;
     
     result = PALLOCTYPE(double);
-    *result = box->yh - box->yl;
+    *result = box->high.y - box->low.y;
     
     return(result);
 }
@@ -318,7 +550,7 @@ double *box_height(BOX *box)
 double *box_distance(BOX *box1, BOX *box2)
 {
     double     *result;
-    Point      *box_center(), *a, *b;
+    Point      *a, *b;
     
     result = PALLOCTYPE(double);
     a = box_center(box1);
@@ -338,8 +570,8 @@ Point *box_center(BOX *box)
     Point      *result;
     
     result = PALLOCTYPE(Point);
-    result->x = (box->xh + box->xl) / 2.0;
-    result->y = (box->yh + box->yl) / 2.0;
+    result->x = (box->high.x + box->low.x) / 2.0;
+    result->y = (box->high.y + box->low.y) / 2.0;
     
     return(result);
 }
@@ -358,7 +590,7 @@ double box_ar(BOX *box)
  */
 double box_ln(BOX *box)
 {
-    return( box->xh - box->xl );
+    return( box->high.x - box->low.x );
 }
 
 
@@ -367,7 +599,7 @@ double box_ln(BOX *box)
  */
 double box_ht(BOX *box)
 {
-    return( box->yh - box->yl );
+    return( box->high.y - box->low.y );
 }
 
 
@@ -377,8 +609,7 @@ double box_ht(BOX *box)
 double box_dt(BOX *box1, BOX *box2)
 {
     double     result;
-    Point      *box_center(),
-    *a, *b;
+    Point      *a, *b;
     
     a = box_center(box1);
     b = box_center(box2);
@@ -400,15 +631,14 @@ double box_dt(BOX *box1, BOX *box2)
 BOX *box_intersect(BOX *box1, BOX *box2)
 {
     BOX        *result;
-    long       box_overlap();
-    
+
     if (! box_overlap(box1,box2))
        return(NULL);
     result = PALLOCTYPE(BOX);
-    result->xh = Min(box1->xh, box2->xh);
-    result->xl = Max(box1->xl, box2->xl);
-    result->yh = Min(box1->yh, box2->yh);
-    result->yl = Max(box1->yl, box2->yl);
+    result->high.x = Min(box1->high.x, box2->high.x);
+    result->low.x = Max(box1->low.x, box2->low.x);
+    result->high.y = Min(box1->high.y, box2->high.y);
+    result->low.y = Max(box1->low.y, box2->low.y);
     
     return(result);
 }
@@ -423,10 +653,10 @@ LSEG *box_diagonal(BOX *box)
 {
     Point      p1, p2;
     
-    p1.x = box->xh;
-    p1.y = box->yh;
-    p2.x = box->xl;
-    p2.y = box->yl;
+    p1.x = box->high.x;
+    p1.y = box->high.y;
+    p2.x = box->low.x;
+    p2.y = box->low.y;
     return( lseg_construct( &p1, &p2 ) );
     
 }
@@ -486,17 +716,17 @@ line_construct_pp(Point *pt1, Point *pt2)
  *  Relative position routines.
  *---------------------------------------------------------*/
 
-long line_intersect(LINE *l1, LINE *l2)
+bool line_intersect(LINE *l1, LINE *l2)
 {
     return( ! line_parallel(l1, l2) );
 }
 
-long line_parallel(LINE *l1, LINE *l2)
+bool line_parallel(LINE *l1, LINE *l2)
 {
     return( FPeq(l1->m, l2->m) );
 }
 
-long line_perp(LINE *l1, LINE *l2)
+bool line_perp(LINE *l1, LINE *l2)
 {
     if (l1->m)
        return( FPeq(l2->m / l1->m, -1.0) );
@@ -505,18 +735,18 @@ long line_perp(LINE *l1, LINE *l2)
     return(1); /* both 0.0 */
 }
 
-long line_vertical(LINE *line)
+bool line_vertical(LINE *line)
 {
     return( FPeq(line->A, -1.0) && FPzero(line->B) );
 }
 
-long line_horizontal(LINE *line)
+bool line_horizontal(LINE *line)
 {
     return( FPzero(line->m) );
 }
 
 
-long line_eq(LINE *l1, LINE *l2)
+bool line_eq(LINE *l1, LINE *l2)
 {
     double     k;
     
@@ -589,88 +819,116 @@ line_interpt(LINE *l1, LINE *l2)
  **
  ***********************************************************************/
 
-#define        PATHALLOCSIZE(N) \
-    (long) ((unsigned) (sizeof(PATH) + \
-                       (((N)-1) > 0 ? ((N)-1) : 0) \
-                       * sizeof(Point)))
-
 /*----------------------------------------------------------
  *  String to path / path to string conversion.
  *     External format: 
+ *             "((xcoord, ycoord),... )"
+ *             "[(xcoord, ycoord),... ]"
+ *             "(xcoord, ycoord),... "
+ *             "[xcoord, ycoord,... ]"
+ *     Also support older format:
  *             "(closed, npts, xcoord, ycoord,... )"
  *---------------------------------------------------------*/
 
 PATH *path_in(char *str)
 {
-    double     coord;
-    long       field[2];
-    char       *s;
-    int        ct, i;
-    PATH       *result;
-    long       pathsize;
-    
-    if (str == NULL)
+    PATH *path;
+
+    int isopen;
+    char *s;
+    int npts;
+    int size;
+#if OLD_FORMAT_IN
+    int oldstyle = FALSE;
+    double x, y;
+#endif
+
+    if (!PointerIsValid((char *)str))
        elog(WARN, "Bad (null) path external representation");
-    
-    /* read the path header information */
-    for (i = 0, s = str; *s && i < 2 && *s != RDELIM; ++s)
-       if (*s == DELIM || (*s == LDELIM && !i))
-           field[i++] = atol(s + 1);
-    if (i < 1)
-       elog(WARN, "Bad path external representation '%s'", str);
-    pathsize = PATHALLOCSIZE(field[1]);
-    result = (PATH *)palloc(pathsize);
-    result->length = pathsize;
-    result->closed = field[0];
-    result->npts =  field[1];
-    
-    /* read the path points */
-    
-    ct = result->npts * 2;     /* two coords for every point */
-    for (i = 0;
-        *s && i < ct && *s != RDELIM; 
-        ++s) {
-       if (*s == ',') {
-           coord = atof(s + 1);
-           if (i % 2)
-               (result->p[i/2]).y = coord;
-           else
-               (result->p[i/2]).x = coord;
-           ++i;
-       }
-    }
-    if (i % 2 || i < --ct) {
-       PFREE(result);
+
+    if ((npts = pair_count(str, ',')) <= 0)
        elog(WARN, "Bad path external representation '%s'", str);
-    } 
-    
-    return(result);
+
+#if OLD_FORMAT_IN
+    s = str;
+    while (isspace( *s)) s++;
+    /* identify old style format as having only one left delimiter in string... */
+    oldstyle = ((*s == LDELIM) && (strrchr( s, LDELIM) == s));
+
+    /* old-style format? then first two fields are closed flag and point count... */
+    if (oldstyle) {
+       s++;
+       if ((! pair_decode( s, &x, &y, &s)) || (*s++ != DELIM)
+         || ((x != 0) && (x != 1)) || (y <= 0))
+           elog (WARN, "Bad path external representation '%s'",str);
+       isopen = (x == 0);
+       npts = y;
+    };
+#endif
+
+    size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * npts);
+    if (!PointerIsValid(path = PALLOC(size)))
+       elog(WARN, "Memory allocation failed, can't input path '%s'",str);
+
+    path->size = size;
+    path->npts =  npts;
+    if (oldstyle) path->closed = (! isopen);
+
+#if OLD_FORMAT_IN
+    if ((! path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0])))
+     || ! (oldstyle? (*s++ == RDELIM): (*s == '\0')))
+#else
+    if ((! path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0])))
+     || (*s != '\0'))
+#endif
+       elog (WARN, "Bad path external representation '%s'",str);
+
+#if OLD_FORMAT_IN
+    if (oldstyle) {
+       while (isspace( *s)) s++;
+       if (*s != '\0')
+           elog (WARN, "Bad path external representation '%s'",str);
+    };
+#endif
+
+    if (! oldstyle) path->closed = (! isopen);
+
+    return(path);
 }
 
 
 char *path_out(PATH *path)
 {
-    char               buf[BUFSIZ + 20000], *result, *s;
-    int                i;
-    char       tmp[64];
-    
-    if (path == NULL)
-       return(NULL);
-    (void) sprintf(buf,"%c%d,%d", LDELIM, 
-                  path->closed, path->npts);
-    s = buf + strlen(buf);
-    for (i = 0; i < path->npts; ++i) {
-       (void) sprintf(tmp, ",%G,%G", 
-                      path->p[i].x, path->p[i].y);
-       (void) strcpy(s, tmp);
-       s += strlen(tmp);
-    }
-    *s++ = RDELIM;
-    *s = '\0';
-    result = (char *)PALLOC(strlen(buf) + 1);
-    (void) strcpy(result, buf);
-    
+#if OLD_FORMAT_OUT
+    int i;
+    char *result, *cp;
+#endif
+
+    if (!PointerIsValid((char *)path))
+       return NULL;
+
+#if OLD_FORMAT_OUT
+    if (!PointerIsValid(result = (char *)PALLOC(path->npts*(P_MAXLEN+3)+2)))
+       elog(WARN, "Memory allocation failed, can't output path", NULL);
+
+    cp = result;
+    *cp++ = LDELIM;
+    if (! pair_encode( path->closed, path->npts, cp))
+       elog (WARN, "Unable to format path", NULL);
+    cp += strlen(cp);
+
+    for (i=0; i<path->npts; i++) {
+        *cp++ = DELIM;
+       if (! pair_encode( path->p[i].x, path->p[i].y, cp))
+           elog (WARN, "Unable to format path", NULL);
+       cp += strlen(cp);
+    };
+    *cp++ = RDELIM;
+    *cp = '\0';
     return(result);
+#else
+    return( path_encode( path->closed, path->npts, (Point *) &(path->p[0])));
+#endif
 }
 
 
@@ -682,55 +940,133 @@ char *path_out(PATH *path)
  *     Better relops and access methods coming soon.
  *---------------------------------------------------------*/
 
-long path_n_lt(PATH *p1, PATH *p2)
+bool path_n_lt(PATH *p1, PATH *p2)
 {
     return( (p1->npts < p2->npts ) );
 }
 
-long path_n_gt(PATH *p1, PATH *p2)
+bool path_n_gt(PATH *p1, PATH *p2)
 {
     return( (p1->npts > p2->npts ) );
 }
 
-long path_n_eq(PATH *p1, PATH *p2)
+bool path_n_eq(PATH *p1, PATH *p2)
 {
     return( (p1->npts == p2->npts) );
 }
 
-long path_n_le(PATH *p1, PATH *p2)
+bool path_n_le(PATH *p1, PATH *p2)
 {
     return( (p1->npts <= p2->npts ) );
 }
 
-long path_n_ge(PATH *p1, PATH *p2)
+bool path_n_ge(PATH *p1, PATH *p2)
 {
     return( (p1->npts >= p2->npts ) );
 }
 
+
+/*----------------------------------------------------------
+ * Conversion operators.
+ *---------------------------------------------------------*/
+
+PATH *path_copy(PATH *path);
+
+bool
+path_isclosed( PATH *path)
+{
+    if (!PointerIsValid((char *)path))
+       return FALSE;
+
+    return(path->closed);
+} /* path_isclosed() */
+
+bool
+path_isopen( PATH *path)
+{
+    if (!PointerIsValid((char *)path))
+       return FALSE;
+
+    return(! path->closed);
+} /* path_isopen() */
+
+
+int4
+path_npoints( PATH *path)
+{
+    if (!PointerIsValid((char *)path))
+       return 0;
+
+    return(path->npts);
+} /* path_npoints() */
+
+PATH *
+path_close(PATH *path)
+{
+    PATH *result;
+
+    if (PointerIsValid((char *)result = path_copy(path)))
+       result->closed = TRUE;
+
+    return(result);
+} /* path_close() */
+
+PATH *
+path_open(PATH *path)
+{
+    PATH *result;
+
+    if (PointerIsValid((char *)result = path_copy(path)))
+       result->closed = FALSE;
+
+    return(result);
+} /* path_open() */
+
+
+PATH *
+path_copy(PATH *path)
+{
+    PATH *result;
+    int size;
+
+    if (!PointerIsValid((char *)path))
+       return NULL;
+
+    size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * path->npts);
+    if (!PointerIsValid(result = PALLOC(size)))
+       elog(WARN, "Memory allocation failed, can't copy path",NULL);
+
+    memmove((char *) result, (char *) path, size);
+    return(result);
+} /* path_copy() */
+
+
 /* path_inter -
  *     Does p1 intersect p2 at any point?
  *     Use bounding boxes for a quick (O(n)) check, then do a 
  *     O(n^2) iterative edge check.
  */
-long path_inter(PATH *p1, PATH *p2)
+bool path_inter(PATH *p1, PATH *p2)
 {
     BOX        b1, b2;
     int        i, j;
     LSEG seg1, seg2;
     
-    b1.xh = b1.yh = b2.xh = b2.yh = (double)DBL_MAX;
-    b1.xl = b1.yl = b2.xl = b2.yl = -(double)DBL_MAX;
-    for (i = 0; i < p1->npts; ++i) {
-       b1.xh = Max(p1->p[i].x, b1.xh);
-       b1.yh = Max(p1->p[i].y, b1.yh);
-       b1.xl = Min(p1->p[i].x, b1.xl);
-       b1.yl = Min(p1->p[i].y, b1.yl);
+    b1.high.x = b1.low.x = p1->p[0].x;
+    b1.high.y = b1.low.y = p1->p[0].y;
+    for (i = 1; i < p1->npts; i++) {
+       b1.high.x = Max(p1->p[i].x, b1.high.x);
+       b1.high.y = Max(p1->p[i].y, b1.high.y);
+       b1.low.x = Min(p1->p[i].x, b1.low.x);
+       b1.low.y = Min(p1->p[i].y, b1.low.y);
     }
-    for (i = 0; i < p2->npts; ++i) {
-       b2.xh = Max(p2->p[i].x, b2.xh);
-       b2.yh = Max(p2->p[i].y, b2.yh);
-       b2.xl = Min(p2->p[i].x, b2.xl);
-       b2.yl = Min(p2->p[i].y, b2.yl);
+    b2.high.x = b2.low.x = p2->p[0].x;
+    b2.high.y = b2.low.y = p2->p[0].y;
+    for (i = 1; i < p2->npts; i++) {
+       b2.high.x = Max(p2->p[i].x, b2.high.x);
+       b2.high.y = Max(p2->p[i].y, b2.high.y);
+       b2.low.x = Min(p2->p[i].x, b2.low.x);
+       b2.low.y = Min(p2->p[i].y, b2.low.y);
     }
     if (! box_overlap(&b1, &b2))
        return(0);
@@ -753,25 +1089,31 @@ long path_inter(PATH *p1, PATH *p2)
    two paths, and finds the min distance between any two lsegs */
 double *path_distance(PATH *p1, PATH *p2)
 {
-    double *min, *tmp;
+    double *min = NULL, *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]);
                
-               if (*min < *(tmp = lseg_distance(&seg1, &seg2)))
-                   *min = *tmp;
-               PFREE(tmp);
+               tmp = lseg_distance(&seg1, &seg2);
+               if ((min == NULL) || (*min < *tmp)) {
+                   if (min != NULL) PFREE(min);
+                   min = tmp;
+               } else {
+                   PFREE(tmp);
+               };
            }
-    
+
     return(min);
 }
 
@@ -782,12 +1124,12 @@ double *path_distance(PATH *p1, PATH *p2)
 
 double *path_length(PATH *path)
 {
-    double     *result;
+    double *result;
     int        ct, i;
     
     result = PALLOCTYPE(double);
     ct = path->npts - 1;
-    for (i = 0; i < ct; ++i)
+    for (i = 0; i < ct; i++)
        *result += point_dt(&path->p[i], &path->p[i+1]);
     
     return(result);
@@ -797,11 +1139,11 @@ double *path_length(PATH *path)
 
 double path_ln(PATH *path)
 {
-    double     result;
+    double result;
     int        ct, i;
     
     ct = path->npts - 1;
-    for (result = i = 0; i < ct; ++i)
+    for (result = i = 0; i < ct; i++)
        result += point_dt(&path->p[i], &path->p[i+1]);
     
     return(result);
@@ -814,52 +1156,49 @@ double path_ln(PATH *path)
 
 /*----------------------------------------------------------
  *  String to point, point to string conversion.
- *     External form:  "(x, y)"
+ *     External format:
+ *             "(x,y)"
+ *             "x,y"
  *---------------------------------------------------------*/
 
-Point *point_in(char *str)
+Point *
+point_in(char *str)
 {
-    char       *coord[POINTNARGS], *p, *r;
-    int        i;
-    Point      *result;
+    Point *point;
+
+    double x, y;
+    char *s;
     
-    if (str == NULL)
+    if (str == NULL) {
        elog(WARN, "Bad (null) point external representation");
-    
-    if ((p = (char *)strchr(str, LDELIM)) == (char *)NULL)
-       elog (WARN, "Bad point external representation '%s'",str);
-    for (i = 0, p++; *p && i < POINTNARGS-1 && *p != RDELIM; p = r+1)
-       if ((r = (char *)strchr(p, DELIM)) == (char *)NULL)
-           elog (WARN, "Bad point external representation '%s'",str);
-       else    
-           coord[i++] = p;
-    if ((r = (char *)strchr(p, RDELIM)) == (char *)NULL)
-       elog (WARN, "Bad point external representation '%s'",str);
-    coord[i++] = p;
-    
-    if (i < POINTNARGS - 1)
-       elog(WARN, "Bad point external representation '%s'",str);
-    result = PALLOCTYPE(Point);
-    result->x = atof(coord[0]);
-    result->y = atof(coord[1]);
-    return(result);
-}
+       return NULL;
+    }
+
+    if (! pair_decode( str, &x, &y, &s) || (strlen(s) > 0))
+      elog (WARN, "Bad point external representation '%s'",str);
 
-char *point_out(Point *pt)
+    if (!PointerIsValid(point = PALLOCTYPE(Point)))
+      elog (WARN, "Unable to allocate point storage for '%s'",str);
+
+    point->x = x;
+    point->y = y;
+
+    return(point);
+} /* point_in() */
+
+char *
+point_out(Point *pt)
 {
-    char       *result;
-    
-    if (pt == NULL)
+    if (!PointerIsValid((char *)pt))
        return(NULL);
-    result = (char *)PALLOC(40);
-    (void) sprintf(result, "(%G,%G)", pt->x, pt->y);
-    return(result);
-}
+
+    return( path_encode( -1, 1, pt));
+} /* point_out() */
 
 
 Point *point_construct(double x, double y)
 {
-    Point      *result;
+    Point *result;
     
     result = PALLOCTYPE(Point);
     result->x = x;
@@ -870,7 +1209,7 @@ Point *point_construct(double x, double y)
 
 Point *point_copy(Point *pt)
 {
-    Point      *result;
+    Point *result;
     
     result = PALLOCTYPE(Point);
     result->x = pt->x;
@@ -888,37 +1227,37 @@ Point *point_copy(Point *pt)
  *     EPSILON = 0.0).
  *---------------------------------------------------------*/
 
-long point_left(Point *pt1, Point *pt2)
+bool point_left(Point *pt1, Point *pt2)
 {
     return( FPlt(pt1->x, pt2->x) );
 }
 
-long point_right(Point *pt1, Point *pt2)
+bool point_right(Point *pt1, Point *pt2)
 {
     return( FPgt(pt1->x, pt2->x) );
 }
 
-long point_above(Point *pt1, Point *pt2)
+bool point_above(Point *pt1, Point *pt2)
 {
     return( FPgt(pt1->y, pt2->y) );
 }
 
-long point_below(Point *pt1, Point *pt2)
+bool point_below(Point *pt1, Point *pt2)
 {
     return( FPlt(pt1->y, pt2->y) );
 }
 
-long point_vert(Point *pt1, Point *pt2)
+bool point_vert(Point *pt1, Point *pt2)
 {
     return( FPeq( pt1->x, pt2->x ) );
 }
 
-long point_horiz(Point *pt1, Point *pt2)
+bool point_horiz(Point *pt1, Point *pt2)
 {
     return( FPeq( pt1->y, pt2->y ) );
 }
 
-long point_eq(Point *pt1, Point *pt2)
+bool point_eq(Point *pt1, Point *pt2)
 {
     return( point_horiz(pt1, pt2) && point_vert(pt1, pt2) );
 }
@@ -927,9 +1266,9 @@ long point_eq(Point *pt1, Point *pt2)
  *  "Arithmetic" operators on points.
  *---------------------------------------------------------*/
 
-long pointdist(Point *p1, Point *p2)
+int32 pointdist(Point *p1, Point *p2)
 {
-    long result;
+    int32 result;
     
     result = point_dt(p1, p2);
     return(result);
@@ -937,7 +1276,7 @@ long pointdist(Point *p1, Point *p2)
 
 double *point_distance(Point *pt1, Point *pt2)
 {
-    double     *result;
+    double *result;
     
     result = PALLOCTYPE(double);
     *result = HYPOT( pt1->x - pt2->x, pt1->y - pt2->y );
@@ -952,7 +1291,7 @@ double point_dt(Point *pt1, Point *pt2)
 
 double *point_slope(Point *pt1, Point *pt2)
 {
-    double     *result;
+    double *result;
     
     result = PALLOCTYPE(double);
     if (point_vert(pt1, pt2))
@@ -970,6 +1309,7 @@ double point_sl(Point *pt1, Point *pt2)
           : (pt1->y - pt2->y) / (pt1->x - pt2->x) );
 }
 
+
 /***********************************************************************
  **
  **    Routines for 2D line segments.
@@ -978,46 +1318,42 @@ double point_sl(Point *pt1, Point *pt2)
 
 /*----------------------------------------------------------
  *  String to lseg, lseg to string conversion.
- *     External form:  "(id, info, x1, y1, x2, y2)"
+ *     External forms: "[(x1, y1), (x2, y2)]"
+ *                     "(x1, y1), (x2, y2)"
+ *                     "x1, y1, x2, y2"
+ *     closed form ok  "((x1, y1), (x2, y2))"
+ *     (old form)      "(x1, y1, x2, y2)"
  *---------------------------------------------------------*/
 
 LSEG *lseg_in(char *str)
 {
-    char       *coord[LSEGNARGS], *p;
-    int        i;
-    LSEG       *result;
-    
-    if (str == NULL)
-       elog (WARN," Bad (null) box external representation");
-    
-    if ((p = (char *)strchr(str, LDELIM)) == (char *)NULL)
+    LSEG *lseg;
+
+    int isopen;
+    char *s;
+
+    if (!PointerIsValid((char *)str))
+       elog (WARN," Bad (null) lseg external representation",NULL);
+
+    if (!PointerIsValid(lseg = PALLOCTYPE(LSEG)))
+      elog(WARN, "Memory allocation failed, can't input lseg '%s'",str);
+
+    if ((! path_decode(TRUE, 2, str, &isopen, &s, &(lseg->p[0])))
+      || (*s != '\0'))
        elog (WARN, "Bad lseg external representation '%s'",str);
-    for (i = 0, p = str; *p && i < LSEGNARGS && *p != RDELIM; p++)
-       if (*p == DELIM || (*p == LDELIM && !i))
-           coord[i++] = p + 1;
-    if (i < LSEGNARGS - 1)
-       elog (WARN, "Bad lseg external representation '%s'", str);
-    result = PALLOCTYPE(LSEG);
-    result->p[0].x = atof(coord[0]);
-    result->p[0].y = atof(coord[1]);
-    result->p[1].x = atof(coord[2]);
-    result->p[1].y = atof(coord[3]);
-    result->m = point_sl(&result->p[0], &result->p[1]);
+
+    lseg->m = point_sl(&lseg->p[0], &lseg->p[1]);
     
-    return(result);
+    return(lseg);
 }
 
 
 char *lseg_out(LSEG *ls)
 {
-    char       *result;
-    
-    if (ls == NULL)
+    if (!PointerIsValid((char *)ls))
        return(NULL);
-    result = (char *)PALLOC(80);
-    (void) sprintf(result, "(%G,%G,%G,%G)",
-                  ls->p[0].x, ls->p[0].y, ls->p[1].x, ls->p[1].y);
-    return(result);
+
+    return( path_encode( FALSE, 2, (Point *) &(ls->p[0])));
 }
 
 
@@ -1033,6 +1369,7 @@ LSEG *lseg_construct(Point *pt1, Point *pt2)
     result->p[0].y = pt1->y;
     result->p[1].x = pt2->x;
     result->p[1].y = pt2->y;
+
     result->m = point_sl(pt1, pt2);
     
     return(result);
@@ -1045,6 +1382,7 @@ void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2)
     lseg->p[0].y = pt1->y;
     lseg->p[1].x = pt2->x;
     lseg->p[1].y = pt2->y;
+
     lseg->m = point_sl(pt1, pt2);
 }
 
@@ -1056,29 +1394,29 @@ void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2)
  **  find intersection of the two lines, and see if it falls on 
  **  both segments.
  */
-long lseg_intersect(LSEG *l1, LSEG *l2)
+bool lseg_intersect(LSEG *l1, LSEG *l2)
 {
     LINE *ln;
     Point *interpt;
-    long retval;
+    bool retval;
     
     ln = line_construct_pp(&l2->p[0], &l2->p[1]);
     interpt = interpt_sl(l1, ln);
     
     if (interpt != NULL && on_ps(interpt, l2)) /* interpt on l1 and l2 */
-       retval = 1;
-    else retval = 0;
+       retval = TRUE;
+    else retval = FALSE;
     if (interpt != NULL) PFREE(interpt);
     PFREE(ln);
     return(retval);
 }
 
-long lseg_parallel(LSEG *l1, LSEG *l2)
+bool lseg_parallel(LSEG *l1, LSEG *l2)
 {
     return( FPeq(l1->m, l2->m) );
 }
 
-long lseg_perp(LSEG *l1, LSEG *l2)
+bool lseg_perp(LSEG *l1, LSEG *l2)
 {
     if (! FPzero(l1->m))
        return( FPeq(l2->m / l1->m, -1.0) );
@@ -1087,18 +1425,18 @@ long lseg_perp(LSEG *l1, LSEG *l2)
     return(0); /* both 0.0 */
 }
 
-long lseg_vertical(LSEG *lseg)
+bool lseg_vertical(LSEG *lseg)
 {
     return( FPeq(lseg->p[0].x, lseg->p[1].x) );
 }
 
-long lseg_horizontal(LSEG *lseg)
+bool lseg_horizontal(LSEG *lseg)
 {
     return( FPeq(lseg->p[0].y, lseg->p[1].y) );
 }
 
 
-long lseg_eq(LSEG *l1, LSEG *l2)
+bool lseg_eq(LSEG *l1, LSEG *l2)
 {
     return( FPeq(l1->p[0].x, l2->p[0].x) &&
           FPeq(l1->p[1].y, l2->p[1].y) &&
@@ -1118,27 +1456,11 @@ long lseg_eq(LSEG *l1, LSEG *l2)
  */
 double *lseg_distance(LSEG *l1, LSEG *l2)
 {
-    double     *d, *result;
+    double *result;
     
     result = PALLOCTYPE(double);
-    if (lseg_intersect(l1, l2)) {
-       *result = 0.0;
-       return(result);
-    }
-    *result = (double)DBL_MAX;
-    d = dist_ps(&l1->p[0], l2);
-    *result = Min(*result, *d);
-    PFREE(d);
-    d = dist_ps(&l1->p[1], l2);
-    *result = Min(*result, *d);
-    PFREE(d);
-    d = dist_ps(&l2->p[0], l1);
-    *result = Min(*result, *d);
-    PFREE(d);
-    d = dist_ps(&l2->p[1], l1);
-    *result = Min(*result, *d);
-    PFREE(d);
-    
+    *result = lseg_dt( l1, l2);
+
     return(result);
 }
 
@@ -1149,9 +1471,9 @@ double lseg_dt(LSEG *l1, LSEG *l2)
     
     if (lseg_intersect(l1, l2))
        return(0.0);
-    result = (double)DBL_MAX;
+
     d = dist_ps(&l1->p[0], l2);
-    result = Min(result, *d);
+    result = *d;
     PFREE(d);
     d = dist_ps(&l1->p[1], l2);
     result = Min(result, *d);
@@ -1265,21 +1587,23 @@ double *dist_ppth(Point *pt, PATH *path)
     LSEG lseg;
     
     switch (path->npts) {
+    /* no points in path? then result is undefined... */
     case 0:
-       result = PALLOCTYPE(double);
-       *result = Abs((double) DBL_MAX);        /* +infinity */
+       result = NULL;
        break;
+    /* one point in path? then get distance between two points... */
     case 1:
        result = point_distance(pt, &path->p[0]);
        break;
     default:
+       /* make sure the path makes sense... */
+       Assert(path->npts > 1);
        /*
         * the distance from a point to a path is the smallest distance
         * from the point to any of its constituent segments.
         */
-       Assert(path->npts > 1);
        result = PALLOCTYPE(double);
-       for (i = 0; i < path->npts - 1; ++i) {
+       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)
@@ -1298,21 +1622,30 @@ double *dist_pb(Point *pt, BOX *box)
     
     tmp = close_pb(pt, box);
     result = point_distance(tmp, pt);
-    
     PFREE(tmp);
+
     return(result);
 }
 
 
 double *dist_sl(LSEG *lseg, LINE *line)
 {
-    double     *result;
-    
+    double *result, *d2;
+
     if (inter_sl(lseg, line)) {
        result = PALLOCTYPE(double);
        *result = 0.0;
-    } else     /* parallel */
+
+    } else {
        result = dist_pl(&lseg->p[0], line);
+       d2 = dist_pl(&lseg->p[1], line);
+       if (*d2 > *result) {
+           PFREE( result);
+           result = d2;
+       } else {
+           PFREE( d2);
+       };
+    };
     
     return(result);
 }
@@ -1502,7 +1835,7 @@ Point *close_lb(LINE *line, BOX *box)
 /* on_pl -
  *     Does the point satisfy the equation? 
  */
-long on_pl(Point *pt, LINE *line)
+bool on_pl(Point *pt, LINE *line)
 {
     return( FPzero(line->A * pt->x + line->B * pt->y + line->C) );
 }
@@ -1511,16 +1844,16 @@ long on_pl(Point *pt, LINE *line)
 /* on_ps -
  *     Determine colinearity by detecting a triangle inequality.
  */
-long on_ps(Point *pt, LSEG *lseg)
+bool on_ps(Point *pt, LSEG *lseg)
 {
     return( FPeq (point_dt(pt, &lseg->p[0]) + point_dt(pt, &lseg->p[1]),
             point_dt(&lseg->p[0], &lseg->p[1])) );
 }
 
-long on_pb(Point *pt, BOX *box)
+bool on_pb(Point *pt, BOX *box)
 {
-    return( pt->x <= box->xh && pt->x >= box->xl &&
-          pt->y <= box->yh && pt->y >= box->yl );
+    return( pt->x <= box->high.x && pt->x >= box->low.x &&
+          pt->y <= box->high.y && pt->y >= box->low.y );
 }
 
 /* on_ppath - 
@@ -1535,7 +1868,7 @@ long on_pb(Point *pt, BOX *box)
  */
 #define NEXT(A)        ((A+1) % path->npts)    /* cyclic "i+1" */
 
-long on_ppath(Point *pt, PATH *path)
+bool on_ppath(Point *pt, PATH *path)
 {
     int        above, next,    /* is the seg above the ray? */
     inter,             /* # of times path crosses ray */
@@ -1604,12 +1937,12 @@ long on_ppath(Point *pt, PATH *path)
 }
 
 
-long on_sl(LSEG *lseg, LINE *line)
+bool on_sl(LSEG *lseg, LINE *line)
 {
     return( on_pl(&lseg->p[0], line) && on_pl(&lseg->p[1], line) );
 }
 
-long on_sb(LSEG *lseg, BOX *box)
+bool on_sb(LSEG *lseg, BOX *box)
 {
     return( on_pb(&lseg->p[0], box) && on_pb(&lseg->p[1], box) );
 }
@@ -1619,7 +1952,7 @@ long on_sb(LSEG *lseg, BOX *box)
  *             Whether one object intersects another.
  *-------------------------------------------------------------------*/
 
-long inter_sl(LSEG *lseg, LINE *line)
+bool inter_sl(LSEG *lseg, LINE *line)
 {
     Point      *tmp;
 
@@ -1631,207 +1964,195 @@ long inter_sl(LSEG *lseg, LINE *line)
     return(0);
 }
 
-long inter_sb(LSEG *lseg, BOX *box)
+/* XXX segment and box should be able to intersect; tgl - 97/01/09 */
+
+bool inter_sb(LSEG *lseg, BOX *box)
 {
     return(0);
 }
 
-long inter_lb(LINE *line, BOX *box)
+/* XXX line and box should be able to intersect; tgl - 97/01/09 */
+
+bool inter_lb(LINE *line, BOX *box)
 {
     return(0);
 }
 
 /*------------------------------------------------------------------
  * The following routines define a data type and operator class for
- * POLYGONS .... Part of which (the polygon's bounding box is built on 
+ * POLYGONS .... Part of which (the polygon's bounding box) is built on 
  * top of the BOX data type.
  *
  * make_bound_box - create the bounding box for the input polygon
  *------------------------------------------------------------------*/
 
-/* Maximum number of output digits printed */
-#define P_MAXDIG 12
-
 /*---------------------------------------------------------------------
  * Make the smallest bounding box for the given polygon.
  *---------------------------------------------------------------------*/
 void make_bound_box(POLYGON *poly)
 {
+    int i;
     double x1,y1,x2,y2;
-    int npts = poly->npts;
-    
-    if (npts > 0) {
-       x1 = poly_min((double *)poly->pts, npts);
-       x2 = poly_max((double *)poly->pts, npts);
-       y1 = poly_min(((double *)poly->pts)+npts, npts),
-       y2 = poly_max(((double *)poly->pts)+npts, npts);
+
+    if (poly->npts > 0) {
+       x2 = x1 = poly->p[0].x;
+       y2 = y1 = poly->p[0].y;
+       for (i = 1; i < poly->npts; i++) {
+           if (poly->p[i].x < x1) x1 = poly->p[i].x;
+           if (poly->p[i].x > x2) x2 = poly->p[i].x;
+           if (poly->p[i].y < y1) y1 = poly->p[i].y;
+           if (poly->p[i].y > y2) y2 = poly->p[i].y;
+       };
+
        box_fill(&(poly->boundbox), x1, x2, y1, y2); 
-    }
+    } else {
+       elog (WARN, "Unable to create bounding box for empty polygon", NULL);
+    };
 }
 
 /*------------------------------------------------------------------
- * polygon_in - read in the polygon from a string specification
- *              the string is of the form "(f8,f8,f8,f8,...,f8)"
+ * poly_in - read in the polygon from a string specification
+ *
+ *     External format:
+ *              "((x0,y0),...,(xn,yn))"
+ *              "x0,y0,...,xn,yn"
+ *             also supports the older style "(x1,...,xn,y1,...yn)"
  *------------------------------------------------------------------*/
-POLYGON *poly_in(char *s)
+POLYGON *poly_in(char *str)
 {
     POLYGON *poly;
-    long points;
-    double *xp, *yp, strtod();
-    int i, size;
-    
-    if((points = poly_pt_count(s, ',')) < 0)
-       elog(WARN, "Bad polygon external representation '%s'", s);
-    
-    size = offsetof(POLYGON, pts[0]) + 2 * sizeof(double) * points;
-    poly = (POLYGON *) PALLOC(size);
+    int npts;
+    int size;
+    int isopen;
+
+#if OLD_FORMAT_IN
+    char *s;
+    int oldstyle;
+    int oddcount;
+    int i;
+    double x1, x2;
+#endif
+
+    if (!PointerIsValid((char *)str))
+       elog (WARN," Bad (null) polygon external representation");
+
+    if ((npts = pair_count(str, ',')) <= 0)
+       elog(WARN, "Bad polygon external representation '%s'", str);
+
+    size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * npts);
+    if (!PointerIsValid(poly = (POLYGON *) PALLOC(size)))
+      elog(WARN, "Memory allocation failed, can't input polygon '%s'",str);
+
     memset((char *) poly, 0, size);    /* zero any holes */
-    
-    if (!PointerIsValid(poly))
-       elog(WARN, "Memory allocation failed, can't input polygon");
-    
-    poly->npts = points;
     poly->size = size;
-    
-    /* Store all x coords followed by all y coords */
-    xp = (double *) &(poly->pts[0]);
-    yp = (double *) (poly->pts + points*sizeof(double));
-    
-    s++;                               /* skip LDELIM */
-    
-    for (i=0; i<points; i++,xp++,yp++)
-       {
-           *xp = strtod(s, &s);
-           s++;                                        /* skip delimiter */
-           *yp = strtod(s, &s);
-           s++;                                        /* skip delimiter */
-       }
+    poly->npts = npts;
+
+#if OLD_FORMAT_IN
+    s = str;
+    while (isspace( *s)) s++;
+    /* identify old style format as having only one left delimiter in string... */
+    oldstyle = ((*s == LDELIM) && (strrchr( s, LDELIM) == s));
+
+    if (oldstyle) {
+       s++;
+       while (isspace( *s)) s++;
+
+       for (i=0; i<npts/2; i++) {
+           if (! pair_decode( s, &x1, &x2, &s))
+               elog (WARN, "Bad polygon external representation '%s'",str);
+
+           if (*s == DELIM) s++;
+           poly->p[i*2].x = x1;
+           poly->p[i*2+1].x = x2;
+       };
+       oddcount = (npts % 2);
+       if (oddcount) {
+           if (! pair_decode( s, &x1, &x2, &s))
+               elog (WARN, "Bad polygon external representation '%s'",str);
+
+           if (*s == DELIM) s++;
+           poly->p[npts-1].x = x1;
+           poly->p[0].y = x2;
+       };
+       for (i=0; i<npts/2; i++) {
+           if (! pair_decode( s, &x1, &x2, &s))
+               elog (WARN, "Bad polygon external representation '%s'",str);
+
+           if (*s == DELIM) s++;
+           poly->p[i*2+oddcount].y = x1;
+           poly->p[i*2+1+oddcount].y = x2;
+       };
+
+       if (*s == RDELIM) {
+           s++;
+           while (isspace( *s)) s++;
+           if (*s != '\0')
+               elog(WARN, "Bad polygon external representation '%s'", str);
+
+       } else {
+           elog(WARN, "Bad polygon external representation '%s'", str);
+       };
+
+    } else {
+#endif
+       if ((! path_decode(FALSE, npts, str, &isopen, &s, &(poly->p[0])))
+         || (*s != '\0'))
+       elog (WARN, "Bad polygon external representation '%s'",str);
+
+#if OLD_FORMAT_IN
+    };
+#endif;
+
     make_bound_box(poly);
-    return (poly);
-}
 
-/*-------------------------------------------------------------
- * poly_pt_count - count the number of points specified in the
- *                 polygon.
- *-------------------------------------------------------------*/
-long poly_pt_count(char *s, char delim)
-{
-    long total = 0;
-    
-    if (*s++ != LDELIM)                /* no left delimeter */
-       return (long) -1;
-    
-    while (*s && (*s != RDELIM))
-       {
-           while (*s && (*s != delim))
-               s++;
-           total++;    /* found one */
-           if (*s)
-               s++;    /* bump s past the delimiter */
-       }
-    
-    /* if there was no right delimiter OR an odd number of points */
-    
-    if ((*(s-1) != RDELIM) || ((total%2) != 0))
-       return (long) -1;
-    
-    return (total/2);
-}
+    return( poly);
+} /* poly_in() */
 
 /*---------------------------------------------------------------
  * poly_out - convert internal POLYGON representation to the 
- *            character string format "(f8,f8,f8,f8,...f8)"
+ *            character string format "((f8,f8),...,(f8,f8))"
+ *            also support old format "(f8,f8,...,f8,f8)"
  *---------------------------------------------------------------*/
 char *poly_out(POLYGON *poly)
 {
+#if OLD_FORMAT_OUT
     int i;
-    double *xp, *yp;
-    char *output, *outptr;
-    
-    /*-----------------------------------------------------
-     * Get enough space for "(f8,f8,f8,f8,...,f8)"
-     * which P_MAXDIG+1 for each coordinate plus 2
-     * for parens and 1 for the null
-     *-----------------------------------------------------*/
-    output = (char *)PALLOC(2*(P_MAXDIG+1)*poly->npts + 3);
-    outptr = output;
-    
-    if (!output)
-       elog(WARN, "Memory allocation failed, can't output polygon");
-    
-    *outptr++ = LDELIM;
-    
-    xp = (double *) poly->pts;
-    yp = (double *) (poly->pts + (poly->npts * sizeof(double)));
-    
-    sprintf(outptr, "%*g,%*g", P_MAXDIG, *xp++, P_MAXDIG, *yp++);
-    outptr += (2*P_MAXDIG + 1);
-    
-    for (i=1; i<poly->npts; i++,xp++,yp++)
-       {
-           sprintf(outptr, ",%*g,%*g", P_MAXDIG, *xp, P_MAXDIG, *yp);
-           outptr += 2*(P_MAXDIG + 1);
-       }
-    *outptr++ = RDELIM;
-    *outptr = '\0';
-    return (output);
-}
-
-/*-------------------------------------------------------
- * Find the largest coordinate out of n coordinates
- *-------------------------------------------------------*/
-double poly_max(double *coords, int ncoords)
-{
-    double max;
-    
-    max = *coords++;
-    ncoords--;
-    while (ncoords--)
-       {
-           if (*coords > max)
-               max = *coords;
-           coords++;
-       }
-    return max;
+    char *result, *cp;
+#endif
+
+    if (!PointerIsValid((char *)poly))
+       return NULL;
+
+#if OLD_FORMAT_OUT
+    if (!PointerIsValid(result = (char *)PALLOC(poly->npts*(P_MAXLEN+3)+2)))
+       elog(WARN, "Memory allocation failed, can't output polygon", NULL);
+
+    cp = result;
+    *cp++ = LDELIM;
+
+    for (i=0; i<poly->npts; i++) {
+       if (! pair_encode( poly->p[i].x, poly->p[i].y, cp))
+           elog (WARN, "Unable to format polygon", NULL);
+       cp += strlen(cp);
+       *cp++ = DELIM;
+    };
+    *(cp-1) = RDELIM;
+    *cp = '\0';
+    return(result);
+#else
+    return( path_encode( TRUE, poly->npts, &(poly->p[0])));
+#endif
 }
 
-/*-------------------------------------------------------
- * Find the smallest coordinate out of n coordinates
- *-------------------------------------------------------*/
-double poly_min(double *coords, int ncoords)
-{
-    double min;
-    
-    min = *coords++;
-    ncoords--;
-    while (ncoords--)
-       {
-           if (*coords < min)
-               min = *coords;
-           coords++;
-       }
-    return min;
-}
 
 /*-------------------------------------------------------
  * Is polygon A strictly left of polygon B? i.e. is
  * the right most point of A left of the left most point
  * of B?
  *-------------------------------------------------------*/
-long poly_left(POLYGON *polya, POLYGON *polyb)
+bool poly_left(POLYGON *polya, POLYGON *polyb)
 {
-    double right, left;
-    
-    if (polya->npts > 0)
-       right = poly_max((double *)polya->pts, polya->npts);
-    else
-       right = polya->boundbox.xh;
-    if (polyb->npts > 0)
-       left = poly_min((double *)polyb->pts, polyb->npts);
-    else
-       left = polyb->boundbox.xl;
-    
-    return (right < left);
+    return (polya->boundbox.high.x < polyb->boundbox.low.x);
 }
 
 /*-------------------------------------------------------
@@ -1839,20 +2160,9 @@ long poly_left(POLYGON *polya, POLYGON *polyb)
  * the left most point of A left of the right most point
  * of B?
  *-------------------------------------------------------*/
-long poly_overleft(POLYGON *polya, POLYGON *polyb)
+bool poly_overleft(POLYGON *polya, POLYGON *polyb)
 {
-    double left, right;
-    
-    if (polya->npts > 0)
-       left = poly_min((double *)polya->pts, polya->npts);
-    else
-       left = polya->boundbox.xl;
-    if (polyb->npts > 0)
-       right = poly_max((double *)polyb->pts, polyb->npts);
-    else
-       right = polyb->boundbox.xh;
-    
-    return (left <= right);
+    return (polya->boundbox.low.x <= polyb->boundbox.high.x);
 }
 
 /*-------------------------------------------------------
@@ -1860,20 +2170,9 @@ long poly_overleft(POLYGON *polya, POLYGON *polyb)
  * the left most point of A right of the right most point
  * of B?
  *-------------------------------------------------------*/
-long poly_right(POLYGON *polya, POLYGON *polyb)
+bool poly_right(POLYGON *polya, POLYGON *polyb)
 {
-    double right, left;
-    
-    if (polya->npts > 0)
-       left = poly_min((double *)polya->pts, polya->npts);
-    else
-       left = polya->boundbox.xl;
-    if (polyb->npts > 0)
-       right = poly_max((double *)polyb->pts, polyb->npts);
-    else
-       right = polyb->boundbox.xh;
-    
-    return (left > right);
+    return( polya->boundbox.low.x > polyb->boundbox.high.x);
 }
 
 /*-------------------------------------------------------
@@ -1881,50 +2180,34 @@ long poly_right(POLYGON *polya, POLYGON *polyb)
  * the right most point of A right of the left most point
  * of B?
  *-------------------------------------------------------*/
-long poly_overright(POLYGON *polya, POLYGON *polyb)
+bool poly_overright(POLYGON *polya, POLYGON *polyb)
 {
-    double right, left;
-    
-    if (polya->npts > 0)
-       right = poly_max((double *)polya->pts, polya->npts);
-    else
-       right = polya->boundbox.xh;
-    if (polyb->npts > 0)
-       left = poly_min((double *)polyb->pts, polyb->npts);
-    else
-       left = polyb->boundbox.xl;
-    
-    return (right > left);
+    return( polya->boundbox.high.x > polyb->boundbox.low.x);
 }
 
 /*-------------------------------------------------------
  * Is polygon A the same as polygon B? i.e. are all the
  * points the same?
  *-------------------------------------------------------*/
-long poly_same(POLYGON *polya, POLYGON *polyb)
+bool poly_same(POLYGON *polya, POLYGON *polyb)
 {
     int i;
-    double *axp, *bxp; /* point to x coordinates for a and b */
-    
     if (polya->npts != polyb->npts)
-       return 0;
-    
-    axp = (double *)polya->pts;
-    bxp = (double *)polyb->pts;
-    
-    for (i=0; i<polya->npts; axp++, bxp++, i++)
-       {
-           if (*axp != *bxp)
-               return 0;
-       }
-    return 1;
+       return FALSE;
+
+    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;
 }
 
 /*-----------------------------------------------------------------
  * Determine if polygon A overlaps polygon B by determining if
  * their bounding boxes overlap.
  *-----------------------------------------------------------------*/
-long poly_overlap(POLYGON *polya, POLYGON *polyb)
+bool poly_overlap(POLYGON *polya, POLYGON *polyb)
 {
     return box_overlap(&(polya->boundbox), &(polyb->boundbox));
 }
@@ -1933,7 +2216,7 @@ long poly_overlap(POLYGON *polya, POLYGON *polyb)
  * Determine if polygon A contains polygon B by determining if A's
  * bounding box contains B's bounding box.
  *-----------------------------------------------------------------*/
-long poly_contain(POLYGON *polya, POLYGON *polyb)
+bool poly_contain(POLYGON *polya, POLYGON *polyb)
 {
     return box_contain(&(polya->boundbox), &(polyb->boundbox));
 }
@@ -1942,7 +2225,995 @@ long poly_contain(POLYGON *polya, POLYGON *polyb)
  * Determine if polygon A is contained by polygon B by determining 
  * if A's bounding box is contained by B's bounding box.
  *-----------------------------------------------------------------*/
-long poly_contained(POLYGON *polya, POLYGON *polyb)
+bool poly_contained(POLYGON *polya, POLYGON *polyb)
 {
     return box_contained(&(polya->boundbox), &(polyb->boundbox));
 }
+
+
+/***********************************************************************
+ **
+ **    Routines for 2D points.
+ **
+ ***********************************************************************/
+
+Point *
+point(float8 *x, float8 *y)
+{
+    if (! (PointerIsValid(x) && PointerIsValid(y)))
+       return(NULL);
+
+    return(point_construct(*x, *y));
+} /* point() */
+
+
+Point *
+point_add(Point *p1, Point *p2)
+{
+    Point *result;
+
+    if (! (PointerIsValid(p1) && PointerIsValid(p2)))
+       return(NULL);
+
+    if (!PointerIsValid(result = PALLOCTYPE(Point)))
+       elog(WARN, "Memory allocation failed, can't add points",NULL);
+
+    result->x = (p1->x + p2->x);
+    result->y = (p1->y + p2->y);
+
+    return(result);
+} /* point_add() */
+
+Point *
+point_sub(Point *p1, Point *p2)
+{
+    Point *result;
+
+    if (! (PointerIsValid(p1) && PointerIsValid(p2)))
+       return(NULL);
+
+    if (!PointerIsValid(result = PALLOCTYPE(Point)))
+       elog(WARN, "Memory allocation failed, can't add points",NULL);
+
+    result->x = (p1->x - p2->x);
+    result->y = (p1->y - p2->y);
+
+    return(result);
+} /* point_sub() */
+
+Point *
+point_mul(Point *p1, Point *p2)
+{
+    Point *result;
+
+    if (! (PointerIsValid(p1) && PointerIsValid(p2)))
+       return(NULL);
+
+    if (!PointerIsValid(result = PALLOCTYPE(Point)))
+       elog(WARN, "Memory allocation failed, can't multiply points",NULL);
+
+    result->x = (p1->x*p2->x) - (p1->y*p2->y);
+    result->y = (p1->x*p2->y) + (p1->y*p2->x);
+
+    return(result);
+} /* point_mul() */
+
+Point *
+point_div(Point *p1, Point *p2)
+{
+    Point *result;
+    double div;
+
+    if (! (PointerIsValid(p1) && PointerIsValid(p2)))
+       return(NULL);
+
+    if (!PointerIsValid(result = PALLOCTYPE(Point)))
+       elog(WARN, "Memory allocation failed, can't multiply path",NULL);
+
+    div = (p2->x*p2->x) + (p2->y*p2->y);
+
+    result->x = ((p1->x*p2->x) + (p1->y*p2->y)) / div;
+    result->y = ((p2->x*p1->y) - (p2->y*p1->x)) / div;
+
+    return(result);
+} /* point_div() */
+
+
+/***********************************************************************
+ **
+ **    Routines for 2D boxes.
+ **
+ ***********************************************************************/
+
+BOX *
+box(Point *p1, Point *p2)
+{
+    BOX *result;
+
+    if (! (PointerIsValid(p1) && PointerIsValid(p2)))
+       return(NULL);
+
+    result = box_construct( p1->x, p2->x, p1->y, p2->y);
+
+    return(result);
+} /* box() */
+
+BOX *
+box_add(BOX *box, Point *p)
+{
+    BOX *result;
+
+    if (! (PointerIsValid(box) && PointerIsValid(p)))
+       return(NULL);
+
+    result = box_construct( (box->high.x + p->x), (box->low.x + p->x),
+      (box->high.y + p->y), (box->low.y + p->y));
+
+    return(result);
+} /* box_add() */
+
+BOX *
+box_sub(BOX *box, Point *p)
+{
+    BOX *result;
+
+    if (! (PointerIsValid(box) && PointerIsValid(p)))
+       return(NULL);
+
+    result = box_construct( (box->high.x - p->x), (box->low.x - p->x),
+      (box->high.y - p->y), (box->low.y - p->y));
+
+    return(result);
+} /* box_sub() */
+
+BOX *
+box_mul(BOX *box, Point *p)
+{
+    BOX *result;
+    Point *high, *low;
+
+    if (! (PointerIsValid(box) && PointerIsValid(p)))
+       return(NULL);
+
+    high = point_mul( &box->high, p);
+    low = point_mul( &box->low, p);
+
+    result = box_construct( high->x, low->x, high->y, low->y);
+    PFREE( high);
+    PFREE( low);
+
+    return(result);
+} /* box_mul() */
+
+BOX *
+box_div(BOX *box, Point *p)
+{
+    BOX *result;
+    Point *high, *low;
+
+    if (! (PointerIsValid(box) && PointerIsValid(p)))
+       return(NULL);
+
+    high = point_div( &box->high, p);
+    low = point_div( &box->low, p);
+
+    result = box_construct( high->x, low->x, high->y, low->y);
+    PFREE( high);
+    PFREE( low);
+
+    return(result);
+} /* box_div() */
+
+
+/***********************************************************************
+ **
+ **    Routines for 2D lines.
+ **            Lines are not intended to be used as ADTs per se,
+ **            but their ops are useful tools for other ADT ops.  Thus,
+ **            there are few relops.
+ **
+ ***********************************************************************/
+
+
+/***********************************************************************
+ **
+ **    Routines for 2D paths.
+ **
+ ***********************************************************************/
+
+POLYGON *path_poly(PATH *path);
+
+/* path_add()
+ * Concatenate two paths (only if they are both open).
+ */
+PATH *
+path_add(PATH *p1, PATH *p2)
+{
+    PATH *result;
+    int size;
+    int i;
+
+    if (! (PointerIsValid(p1) && PointerIsValid(p2))
+      || p1->closed || p2->closed)
+       return(NULL);
+
+    size = offsetof(PATH, p[0]) + (sizeof(p1->p[0]) * (p1->npts+p2->npts));
+    if (!PointerIsValid(result = PALLOC(size)))
+       elog(WARN, "Memory allocation failed, can't add paths",NULL);
+
+    result->size = size;
+    result->npts = (p1->npts+p2->npts);
+    result->closed = p1->closed;
+
+    for (i=0; i<p1->npts; i++) {
+       result->p[i].x = p1->p[i].x;
+       result->p[i].y = p1->p[i].y;
+    };
+    for (i=0; i<p2->npts; i++) {
+       result->p[i+p1->npts].x = p2->p[i].x;
+       result->p[i+p1->npts].y = p2->p[i].y;
+    };
+
+    return(result);
+} /* path_add() */
+
+/* path_add_pt()
+ * Translation operator.
+ */
+PATH *
+path_add_pt(PATH *path, Point *point)
+{
+    PATH *result;
+    int i;
+
+    if (! (PointerIsValid(path) && PointerIsValid(point)))
+       return(NULL);
+
+    if (! PointerIsValid(result = path_copy(path)))
+       elog(WARN, "Memory allocation failed, can't add path",NULL);
+
+    for (i=0; i<path->npts; i++) {
+       result->p[i].x += point->x;
+       result->p[i].y += point->y;
+    };
+
+    return(result);
+} /* path_add_pt() */
+
+PATH *
+path_sub_pt(PATH *path, Point *point)
+{
+    PATH *result;
+    int i;
+
+    if (! (PointerIsValid(path) && PointerIsValid(point)))
+       return(NULL);
+
+    if (! PointerIsValid(result = path_copy(path)))
+       elog(WARN, "Memory allocation failed, can't subtract path",NULL);
+
+    for (i=0; i<path->npts; i++) {
+       result->p[i].x -= point->x;
+       result->p[i].y -= point->y;
+    };
+
+    return(result);
+} /* path_sub_pt() */
+
+
+/* path_mul_pt()
+ * Rotation and scaling operators.
+ */
+PATH *
+path_mul_pt(PATH *path, Point *point)
+{
+    PATH *result;
+    Point *p;
+    int i;
+
+    if (! (PointerIsValid(path) && PointerIsValid(point)))
+       return(NULL);
+
+    if (! PointerIsValid(result = path_copy(path)))
+       elog(WARN, "Memory allocation failed, can't multiply path",NULL);
+
+    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;
+       PFREE(p);
+    };
+
+    return(result);
+} /* path_mul_pt() */
+
+PATH *
+path_div_pt(PATH *path, Point *point)
+{
+    PATH *result;
+    Point *p;
+    int i;
+
+    if (! (PointerIsValid(path) && PointerIsValid(point)))
+       return(NULL);
+
+    if (! PointerIsValid(result = path_copy(path)))
+       elog(WARN, "Memory allocation failed, can't divide path",NULL);
+
+    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;
+       PFREE(p);
+    };
+
+    return(result);
+} /* path_div_pt() */
+
+
+POLYGON *path_poly(PATH *path)
+{
+    POLYGON *poly;
+    int size;
+    int i;
+
+    if (!PointerIsValid(path))
+       return(NULL);
+
+    if (!path->closed)
+       elog(WARN, "Open path cannot be converted to polygon",NULL);
+
+    size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * path->npts);
+    if (!PointerIsValid(poly = PALLOC(size)))
+       elog(WARN, "Memory allocation failed, can't convert path to polygon",NULL);
+
+    poly->size = size;
+    poly->npts = path->npts;
+
+    for (i=0; i<path->npts; i++) {
+       poly->p[i].x = path->p[i].x;
+       poly->p[i].y = path->p[i].y;
+    };
+
+    make_bound_box(poly);
+
+    return(poly);
+} /* path_polygon() */
+
+
+/***********************************************************************
+ **
+ **    Routines for 2D polygons.
+ **
+ ***********************************************************************/
+
+int4
+poly_npoints( POLYGON *poly)
+{
+    if (!PointerIsValid(poly))
+       return(0);
+
+    return(poly->npts);
+} /* poly_npoints() */
+
+BOX *
+poly_box(POLYGON *poly)
+{
+    BOX *box;
+
+    if (!PointerIsValid(poly) || (poly->npts < 1))
+       return(NULL);
+
+    box = box_copy( &poly->boundbox);
+
+    return(box);
+} /* poly_box() */
+
+POLYGON *
+box_poly(BOX *box)
+{
+    POLYGON *poly;
+    int size;
+
+    if (!PointerIsValid(box))
+       return(NULL);
+
+    size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * 4);
+    if (!PointerIsValid(poly = PALLOC(size)))
+       elog(WARN, "Memory allocation failed, can't convert box to polygon",NULL);
+
+    poly->size = size;
+    poly->npts = 4;
+
+    poly->p[0].x = box->low.x;
+    poly->p[0].y = box->low.y;
+    poly->p[1].x = box->low.x;
+    poly->p[1].y = box->high.y;
+    poly->p[2].x = box->high.x;
+    poly->p[2].y = box->high.y;
+    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);
+
+    return(poly);
+} /* box_poly() */
+
+PATH *
+poly_path(POLYGON *poly)
+{
+    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);
+    if (!PointerIsValid(path = PALLOC(size)))
+       elog(WARN, "Memory allocation failed, can't convert polygon to path",NULL);
+
+    path->size = size;
+    path->npts = poly->npts;
+    path->closed = TRUE;
+
+    for (i=0; i<poly->npts; i++) {
+       path->p[i].x = poly->p[i].x;
+       path->p[i].y = poly->p[i].y;
+    };
+
+    return(path);
+} /* poly_path() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * circle.c--
+ *    2D geometric operations
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.3 1997/04/22 17:31:32 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PI
+#define PI 3.1415926536
+#endif
+
+int single_decode(char *str, float8 *x, char **ss);
+int single_encode(float8 x, char *str);
+
+int single_decode(char *str, float8 *x, char **s)
+{
+    char *cp;
+
+    if (!PointerIsValid(str))
+       return(FALSE);
+
+    while (isspace( *str)) str++;
+    *x = strtod( str, &cp);
+#ifdef GEODEBUG
+fprintf( stderr, "single_decode- (%x) try decoding %s to %g\n", (cp-str), str, *x);
+#endif
+    if (cp <= str) return(FALSE);
+    while (isspace( *cp)) cp++;
+
+    if (s != NULL) *s = cp;
+
+    return(TRUE);
+}
+
+int single_encode(float8 x, char *str)
+{
+    (void) sprintf(str, "%.*g", digits8, x);
+    return(TRUE);
+}
+
+
+/***********************************************************************
+ **
+ **    Routines for circles.
+ **
+ ***********************************************************************/
+
+/*----------------------------------------------------------
+ * Formatting and conversion routines.
+ *---------------------------------------------------------*/
+
+/*     circle_in       -       convert a string to internal form.
+ *
+ *     External format: (center and radius of circle)
+ *             "((f8,f8)<f8>)"
+ *             also supports quick entry style "(f8,f8,f8)"
+ */
+CIRCLE *circle_in(char *str)
+{
+    CIRCLE *circle;
+
+    char *s, *cp;
+    int depth = 0;
+
+    if (!PointerIsValid(str))
+       elog (WARN," Bad (null) circle external representation",NULL);
+
+    if (!PointerIsValid(circle = PALLOCTYPE(CIRCLE)))
+      elog(WARN, "Memory allocation failed, can't input circle '%s'",str);
+
+    s = str;
+    while (isspace( *s)) s++;
+    if ((*s == LDELIM_C) || (*s == LDELIM)) {
+       depth++;
+       cp = (s+1);
+       while (isspace( *cp)) cp++;
+       if (*cp == LDELIM) {
+           s = cp;
+       };
+    };
+
+    if (! pair_decode( s, &circle->center.x, &circle->center.y, &s))
+      elog (WARN, "Bad circle external representation '%s'",str);
+
+    if (*s == DELIM) s++;
+    while (isspace( *s)) s++;
+
+    if (! single_decode( s, &circle->radius, &s))
+      elog (WARN, "Bad circle external representation '%s'",str);
+
+    while (depth > 0) {
+       if ((*s == RDELIM)
+         || ((*s == RDELIM_C) && (depth == 1))) {
+           depth--;
+           s++;
+           while (isspace( *s)) s++;
+       } else {
+           elog (WARN, "Bad circle external representation '%s'",str);
+       };
+    };
+
+    if (*s != '\0')
+      elog (WARN, "Bad circle external representation '%s'",str);
+
+    return(circle);
+} /* circle_in() */
+
+/*     circle_out      -       convert a circle to external form.
+ */
+char *circle_out(CIRCLE *circle)
+{
+    char *result;
+    char *cp;
+
+    if (!PointerIsValid(circle))
+       return(NULL);
+
+    if (!PointerIsValid(result = (char *)PALLOC(3*(P_MAXLEN+1)+3)))
+       elog(WARN, "Memory allocation failed, can't output circle", NULL);
+
+    cp = result;
+    *cp++ = LDELIM_C;
+    *cp++ = LDELIM;
+    if (! pair_encode( circle->center.x, circle->center.y, cp))
+         elog (WARN, "Unable to format circle", NULL);
+
+    cp += strlen(cp);
+    *cp++ = RDELIM;
+    *cp++ = DELIM;
+    if (! single_encode( circle->radius, cp))
+         elog (WARN, "Unable to format circle", NULL);
+
+    cp += strlen(cp);
+    *cp++ = RDELIM_C;
+    *cp = '\0';
+
+    return(result);
+} /* circle_out() */
+
+
+/*----------------------------------------------------------
+ *  Relational operators for CIRCLEs.
+ *     <, >, <=, >=, and == are based on circle area.
+ *---------------------------------------------------------*/
+
+/*     circles identical?
+ */
+bool circle_same(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPeq(circle1->radius,circle2->radius)
+      && FPeq(circle1->center.x,circle2->center.x)
+      && FPeq(circle1->center.y,circle2->center.y));
+}
+
+/*     circle_overlap  -       does circle1 overlap circle2?
+ */
+bool circle_overlap(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPle(point_dt(&circle1->center,&circle2->center),(circle1->radius+circle2->radius)));
+}
+
+/*     circle_overleft -       is the right edge of circle1 to the left of
+ *                             the right edge of circle2?
+ */
+bool circle_overleft(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPle((circle1->center.x+circle1->radius),(circle2->center.x+circle2->radius)));
+}
+
+/*     circle_left     -       is circle1 strictly left of circle2?
+ */
+bool circle_left(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPle((circle1->center.x+circle1->radius),(circle2->center.x-circle2->radius)));
+}
+
+/*     circle_right    -       is circle1 strictly right of circle2?
+ */
+bool circle_right(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPge((circle1->center.x-circle1->radius),(circle2->center.x+circle2->radius)));
+}
+
+/*     circle_overright        -       is the left edge of circle1 to the right of
+ *                             the left edge of circle2?
+ */
+bool circle_overright(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPge((circle1->center.x-circle1->radius),(circle2->center.x-circle2->radius)));
+}
+
+/*     circle_contained        -       is circle1 contained by circle2?
+ */
+bool circle_contained(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPle((point_dt(&circle1->center,&circle2->center)+circle1->radius),circle2->radius));
+}
+
+/*     circle_contain  -       does circle1 contain circle2?
+ */
+bool circle_contain(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPle((point_dt(&circle1->center,&circle2->center)+circle2->radius),circle1->radius));
+}
+
+
+/*     circle_positionop       -
+ *             is circle1 entirely {above,below} circle2?
+ */
+bool circle_below(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPle((circle1->center.y+circle1->radius),(circle2->center.y-circle2->radius)));
+}
+
+bool circle_above(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPge((circle1->center.y-circle1->radius),(circle2->center.y+circle2->radius)));
+}
+
+
+/*     circle_relop    -       is area(circle1) relop area(circle2), within
+ *                             our accuracy constraint?
+ */
+bool circle_eq(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPeq(circle_ar(circle1), circle_ar(circle2)) );
+} /* circle_eq() */
+
+bool circle_ne(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( !circle_eq(circle1, circle2));
+} /* circle_ne() */
+
+bool circle_lt(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPlt(circle_ar(circle1), circle_ar(circle2)) );
+} /* circle_lt() */
+
+bool circle_gt(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPgt(circle_ar(circle1), circle_ar(circle2)) );
+} /* circle_gt() */
+
+bool circle_le(CIRCLE *circle1, CIRCLE *circle2)
+{
+    return( FPle(circle_ar(circle1), circle_ar(circle2)) );
+} /* circle_le() */
+
+bool circle_ge(CIRCLE  *circle1, CIRCLE *circle2)
+{
+    return( FPge(circle_ar(circle1), circle_ar(circle2)) );
+} /* circle_ge() */
+
+
+/*----------------------------------------------------------
+ *  "Arithmetic" operators on circles.
+ *     circle_foo      returns foo as an object (pointer) that
+ can be passed between languages.
+ *     circle_xx       is an internal routine which returns the
+ *                     actual value.
+ *---------------------------------------------------------*/
+
+CIRCLE *circle_copy(CIRCLE *circle);
+
+CIRCLE *
+circle_copy(CIRCLE *circle)
+{
+    CIRCLE *result;
+
+    if (!PointerIsValid(circle))
+       return NULL;
+
+    if (!PointerIsValid(result = PALLOCTYPE(CIRCLE)))
+       elog(WARN, "Memory allocation failed, can't copy circle",NULL);
+
+    memmove((char *) result, (char *) circle, sizeof(CIRCLE));
+    return(result);
+} /* circle_copy() */
+
+
+/* circle_add_pt()
+ * Translation operator.
+ */
+CIRCLE *
+circle_add_pt(CIRCLE *circle, Point *point)
+{
+    CIRCLE *result;
+
+    if (!PointerIsValid(circle) && !PointerIsValid(point))
+       return(NULL);
+
+    if (! PointerIsValid(result = circle_copy(circle)))
+       elog(WARN, "Memory allocation failed, can't add circle",NULL);
+
+    result->center.x += point->x;
+    result->center.y += point->y;
+
+    return(result);
+} /* circle_add_pt() */
+
+CIRCLE *
+circle_sub_pt(CIRCLE *circle, Point *point)
+{
+    CIRCLE *result;
+
+    if (!PointerIsValid(circle) && !PointerIsValid(point))
+       return(NULL);
+
+    if (! PointerIsValid(result = circle_copy(circle)))
+       elog(WARN, "Memory allocation failed, can't subtract circle",NULL);
+
+    result->center.x -= point->x;
+    result->center.y -= point->y;
+
+    return(result);
+} /* circle_sub_pt() */
+
+
+/* circle_mul_pt()
+ * Rotation and scaling operators.
+ */
+CIRCLE *
+circle_mul_pt(CIRCLE *circle, Point *point)
+{
+    CIRCLE *result;
+    Point *p;
+
+    if (!PointerIsValid(circle) && !PointerIsValid(point))
+       return(NULL);
+
+    if (! PointerIsValid(result = circle_copy(circle)))
+       elog(WARN, "Memory allocation failed, can't multiply circle",NULL);
+
+    p = point_mul( &circle->center, point);
+    result->center.x = p->x;
+    result->center.y = p->y;
+    PFREE(p);
+    result->radius *= HYPOT( point->x, point->y);
+
+    return(result);
+} /* circle_mul_pt() */
+
+CIRCLE *
+circle_div_pt(CIRCLE *circle, Point *point)
+{
+    CIRCLE *result;
+    Point *p;
+
+    if (!PointerIsValid(circle) && !PointerIsValid(point))
+       return(NULL);
+
+    if (! PointerIsValid(result = circle_copy(circle)))
+       elog(WARN, "Memory allocation failed, can't add circle",NULL);
+
+    p = point_div( &circle->center, point);
+    result->center.x = p->x;
+    result->center.y = p->y;
+    PFREE(p);
+    result->radius /= HYPOT( point->x, point->y);
+
+    return(result);
+} /* circle_div_pt() */
+
+
+/*     circle_area     -       returns the area of the circle.
+ */
+double *circle_area(CIRCLE *circle)
+{
+    double *result;
+
+    result = PALLOCTYPE(double);
+    *result = circle_ar(circle);
+
+    return(result);
+}
+
+
+/*     circle_diameter -       returns the diameter of the circle.
+ */
+double *circle_diameter(CIRCLE *circle)
+{
+    double     *result;
+
+    result = PALLOCTYPE(double);
+    *result = (2*circle->radius);
+
+    return(result);
+}
+
+
+/*     circle_radius   -       returns the radius of the circle.
+ */
+double *circle_radius(CIRCLE *circle)
+{
+    double     *result;
+
+    result = PALLOCTYPE(double);
+    *result = circle->radius;
+
+    return(result);
+}
+
+
+/*     circle_distance -       returns the distance between the
+ *                               center points of two circlees.
+ */
+double *circle_distance(CIRCLE *circle1, CIRCLE *circle2)
+{
+    double     *result;
+
+    result = PALLOCTYPE(double);
+    *result = point_dt(&circle1->center,&circle2->center);
+
+    return(result);
+}
+
+
+/*     circle_center   -       returns the center point of the circle.
+ */
+Point *circle_center(CIRCLE *circle)
+{
+    Point      *result;
+
+    result = PALLOCTYPE(Point);
+    result->x = circle->center.x;
+    result->y = circle->center.y;
+
+    return(result);
+}
+
+
+/*     circle_ar       -       returns the area of the circle.
+ */
+double circle_ar(CIRCLE *circle)
+{
+    return(PI*(circle->radius*circle->radius));
+}
+
+
+/*     circle_dt       -       returns the distance between the
+ *                       center points of two circlees.
+ */
+double circle_dt(CIRCLE *circle1, CIRCLE *circle2)
+{
+    double     result;
+
+    result = point_dt(&circle1->center,&circle2->center);
+
+    return(result);
+}
+
+
+/*----------------------------------------------------------
+ *  Conversion operators.
+ *---------------------------------------------------------*/
+
+CIRCLE *circle(Point *center, float8 *radius)
+{
+    CIRCLE *result;
+
+    if (! (PointerIsValid(center) && PointerIsValid(radius)))
+       return(NULL);
+
+    if (!PointerIsValid(result = PALLOCTYPE(CIRCLE)))
+      elog(WARN, "Memory allocation failed, can't convert point to circle",NULL);
+
+    result->center.x = center->x;
+    result->center.y = center->y;
+    result->radius = *radius;
+
+    return(result);
+}
+
+POLYGON *circle_poly(int npts, CIRCLE *circle)
+{
+    POLYGON *poly;
+    int size;
+    int i;
+    double angle;
+
+    if (!PointerIsValid(circle))
+       return(NULL);
+
+    if (FPzero(circle->radius) || (npts <= 2))
+         elog (WARN, "Unable to convert circle to polygon", NULL);
+
+    size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * npts);
+    if (!PointerIsValid(poly = (POLYGON *) PALLOC(size)))
+      elog(WARN, "Memory allocation failed, can't convert circle to polygon",NULL);
+
+    memset((char *) poly, 0, size);    /* zero any holes */
+    poly->size = size;
+    poly->npts = npts;
+
+    for (i=0;i<npts;i++) {
+       angle = i*(2*PI/npts);
+       poly->p[i].x = circle->center.x - (circle->radius*cos(angle));
+       poly->p[i].y = circle->center.y + (circle->radius*sin(angle));
+    };
+
+    make_bound_box(poly);
+
+    return(poly);
+}
+
+/*     poly_circle     - convert polygon to circle
+ *
+ * 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)
+{
+    CIRCLE *circle;
+    int i;
+
+    if (!PointerIsValid(poly))
+       return(NULL);
+
+    if (poly->npts <= 2)
+         elog (WARN, "Unable to convert polygon to circle", NULL);
+
+    if (!PointerIsValid(circle = PALLOCTYPE(CIRCLE)))
+      elog(WARN, "Memory allocation failed, can't convert polygon to circle",NULL);
+
+    circle->center.x = 0;
+    circle->center.y = 0;
+    circle->radius = 0;
+
+    for (i=0;i<poly->npts;i++) {
+       circle->center.x += poly->p[i].x;
+       circle->center.y += poly->p[i].y;
+    };
+    circle->center.x /= poly->npts;
+    circle->center.y /= poly->npts;
+
+    for (i=0;i<poly->npts;i++) {
+       circle->radius += point_dt( &poly->p[i], &circle->center);
+    };
+    circle->radius /= poly->npts;
+
+    if (FPzero(circle->radius))
+         elog (WARN, "Unable to convert polygon to circle", NULL);
+
+    return(circle);
+}
index fa8a48068733a144d318df64814b0d5ed02dde96..2b61ac73edcafb3299c8b29c624109190717e33f 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_operator.h,v 1.8 1997/04/15 17:40:44 scrappy Exp $
+ * $Id: pg_operator.h,v 1.9 1997/04/22 17:31:49 scrappy Exp $
  *
  * NOTES
  *    the genbki.sh script reads this file and generates .bki
@@ -185,7 +185,7 @@ DATA(insert OID = 513 (  "@@"      PGUID 0 l t f   0 603 600   0   0   0   0 box
 DATA(insert OID = 514 (  "*"       PGUID 0 b t f  23  23  23 514   0   0   0 int4mul intltsel intltjoinsel ));
 DATA(insert OID = 515 (  "!"       PGUID 0 r t f  23   0  23   0   0   0   0 int4fac intltsel intltjoinsel ));
 DATA(insert OID = 516 (  "!!"      PGUID 0 l t f   0  23  23   0   0   0   0 int4fac intltsel intltjoinsel ));
-DATA(insert OID = 517 (  "<===>"   PGUID 0 b t f 600 600 701   0   0   0   0 point_distance intltsel intltjoinsel ));
+DATA(insert OID = 517 (  "<===>"   PGUID 0 b t f 600 600 701 517   0   0   0 point_distance intltsel intltjoinsel ));
 DATA(insert OID = 518 (  "<>"      PGUID 0 b t f  23  23  16 518  96  0  0 int4ne neqsel neqjoinsel ));
 DATA(insert OID = 519 (  "<>"      PGUID 0 b t f  21  21  16 519  94  0  0 int2ne neqsel neqjoinsel ));
 DATA(insert OID = 520 (  ">"       PGUID 0 b t f  21  21  16  95   0  0  0 int2gt intgtsel intgtjoinsel ));
@@ -279,6 +279,14 @@ DATA(insert OID = 609 (  "<"       PGUID 0 b t f  26  26  16 610 612  0  0 int4l
 DATA(insert OID = 610 (  ">"       PGUID 0 b t f  26  26  16 609 611  0  0 int4gt intgtsel intgtjoinsel ));
 DATA(insert OID = 611 (  "<="      PGUID 0 b t f  26  26  16 612 610  0  0 int4le intltsel intltjoinsel ));
 DATA(insert OID = 612 (  ">="      PGUID 0 b t f  26  26  16 611 609  0  0 int4ge intgtsel intgtjoinsel ));
+
+DATA(insert OID = 613 (  "<===>"   PGUID 0 b t f 600 603 701 613   0  0  0 dist_pl intltsel intltjoinsel ));
+DATA(insert OID = 614 (  "<===>"   PGUID 0 b t f 600 601 701 614   0  0  0 dist_ps intltsel intltjoinsel ));
+DATA(insert OID = 615 (  "<===>"   PGUID 0 b t f 600 603 701 615   0  0  0 dist_pb intltsel intltjoinsel ));
+DATA(insert OID = 616 (  "<===>"   PGUID 0 b t f 600 603 701 616   0  0  0 dist_ps intltsel intltjoinsel ));
+DATA(insert OID = 617 (  "<===>"   PGUID 0 b t f 601 603 701 617   0  0  0 dist_sb intltsel intltjoinsel ));
+DATA(insert OID = 618 (  "<===>"   PGUID 0 b t f 600 602 701 618   0  0  0 dist_ppth intltsel intltjoinsel ));
+
 DATA(insert OID = 620 (  "="       PGUID 0 b t t  700  700  16 620 621  622 622 float4eq eqsel eqjoinsel ));
 DATA(insert OID = 621 (  "<>"      PGUID 0 b t f  700  700  16 621 620  0 0 float4ne neqsel neqjoinsel ));
 DATA(insert OID = 622 (  "<"       PGUID 0 b t f  700  700  16 623 625  0 0 float4lt intltsel intltjoinsel ));
@@ -341,6 +349,11 @@ DATA(insert OID = 681 (  "<>"      PGUID 0 b t f  911  911  16 681 678  0 0 oidn
 DATA(insert OID = 697 (  "~"       PGUID 0 b t f  411  25  16 0 698  0 0 char8regexeq eqsel eqjoinsel ));
 DATA(insert OID = 698 (  "!~"      PGUID 0 b t f  411  25  16 0 697  0 0 char8regexne neqsel neqjoinsel ));
 
+DATA(insert OID = 706 (  "<===>"   PGUID 0 b t f 603 603 701 706   0  0  0 box_distance intltsel intltjoinsel ));
+DATA(insert OID = 707 (  "<===>"   PGUID 0 b t f 602 602 701 707   0  0  0 path_distance intltsel intltjoinsel ));
+DATA(insert OID = 708 (  "<===>"   PGUID 0 b t f 603 603 701 708   0  0  0 line_distance intltsel intltjoinsel ));
+DATA(insert OID = 709 (  "<===>"   PGUID 0 b t f 601 601 701 709   0  0  0 lseg_distance intltsel intltjoinsel ));
+
 DATA(insert OID = 830 (  "<"       PGUID 0 b t f  810  810  16 834 833  0 0 oidint2lt intltsel intltjoinsel ));
 DATA(insert OID = 831 (  "<="      PGUID 0 b t f  810  810  16 833 834  0 0 oidint2le intltsel intltjoinsel ));
 DATA(insert OID = 832 (  "="       PGUID 0 b t f  810  810  16 832 835  0 0 oidint2eq intltsel intltjoinsel ));
@@ -509,7 +522,32 @@ DATA(insert OID = 1303 (  ">"       PGUID 0 b t f  1296 1296 16 1302 1304 0 0 ti
 DATA(insert OID = 1304 (  "<="      PGUID 0 b t f  1296 1296 16 1305 1303 0 0 timestample intltsel intltjoinsel ));
 DATA(insert OID = 1305 (  ">="      PGUID 0 b t f  1296 1296 16 1304 1302 0 0 timestampge intltsel intltjoinsel ));
 
-
+/* additional geometric operators - tgl 97/04/18 */
+DATA(insert OID = 1500 (  "="     PGUID 0 b t t  718  718   16 1500 1501 1502 1502 circle_eq eqsel eqjoinsel ));
+DATA(insert OID = 1501 (  "<>"    PGUID 0 b t f  718  718   16 1501 1500    0    0 circle_ne neqsel neqjoinsel ));
+DATA(insert OID = 1502 (  "<"     PGUID 0 b t f  718  718   16 1503 1505    0    0 circle_eq eqsel eqjoinsel ));
+DATA(insert OID = 1503 (  ">"     PGUID 0 b t f  718  718   16 1502 1504    0    0 circle_eq eqsel eqjoinsel ));
+DATA(insert OID = 1504 (  "<="    PGUID 0 b t f  718  718   16 1505 1503    0    0 circle_eq eqsel eqjoinsel ));
+DATA(insert OID = 1505 (  ">="    PGUID 0 b t f  718  718   16 1504 1502    0    0 circle_eq eqsel eqjoinsel ));
+
+DATA(insert OID = 1506 (  "<<"    PGUID 0 b t f  718  718   16    0    0    0    0 circle_left intltsel intltjoinsel ));
+DATA(insert OID = 1507 (  "&<"    PGUID 0 b t f  718  718   16    0    0    0    0 circle_overleft intltsel intltjoinsel ));
+DATA(insert OID = 1508 (  "&>"    PGUID 0 b t f  718  718   16    0    0    0    0 circle_overright intltsel intltjoinsel ));
+DATA(insert OID = 1509 (  ">>"    PGUID 0 b t f  718  718   16    0    0    0    0 circle_right intltsel intltjoinsel ));
+DATA(insert OID = 1510 (  "@"     PGUID 0 b t f  718  718   16    0    0    0    0 circle_contained intltsel intltjoinsel ));
+DATA(insert OID = 1511 (  "~"     PGUID 0 b t f  718  718   16    0    0    0    0 circle_contain intltsel intltjoinsel ));
+DATA(insert OID = 1512 (  "~="    PGUID 0 b t f  718  718   16 1512    0    0    0 circle_same intltsel intltjoinsel ));
+DATA(insert OID = 1513 (  "&&"    PGUID 0 b t f  718  718   16    0    0    0    0 circle_overlap intltsel intltjoinsel ));
+DATA(insert OID = 1514 (  "!^"    PGUID 0 b t f  718  718   16    0    0    0    0 circle_above intltsel intltjoinsel ));
+DATA(insert OID = 1515 (  "!|"    PGUID 0 b t f  718  718   16    0    0    0    0 circle_below intltsel intltjoinsel ));
+
+DATA(insert OID = 1516 (  "+"     PGUID 0 b t f  718  600  718 1516    0    0    0 circle_add_pt - - ));
+DATA(insert OID = 1517 (  "-"     PGUID 0 b t f  718  600  718    0    0    0    0 circle_sub_pt - - ));
+DATA(insert OID = 1518 (  "*"     PGUID 0 b t f  718  600  718 1518    0    0    0 circle_mul_pt - - ));
+DATA(insert OID = 1519 (  "/"     PGUID 0 b t f  718  600  718    0    0    0    0 circle_div_pt - - ));
+
+DATA(insert OID = 1520 (  "<===>" PGUID 0 b t f  718  718  701 1520    0    0    0 circle_distance intltsel intltjoinsel ));
+DATA(insert OID = 1521 (  "#"     PGUID 0 l t f    0  604   23    0    0    0    0 poly_npoints - - ));
 
 /*
  * function prototypes
index bd1cf4f208bc003a3c47f9280d02b52681776d59..ff346f04dfd5599dc2c1d7d458bcbf8466367560 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.17 1997/04/15 17:41:03 scrappy Exp $
+ * $Id: pg_proc.h,v 1.18 1997/04/22 17:32:12 scrappy Exp $
  *
  * NOTES
  *    The script catalog/genbki.sh reads this file and generates .bki
@@ -92,6 +92,7 @@ typedef FormData_pg_proc      *Form_pg_proc;
 /* keep the following ordered by OID so that later changes can be made easier*/
 
 /* OIDS 1 - 99 */
+
 DATA(insert OID = 1242 (  boolin           PGUID 11 f t f 1 f 16 "0" 100 0 0  100  foo bar ));
 DATA(insert OID = 1243 (  boolout          PGUID 11 f t f 1 f 23 "0" 100 0 0 100  foo bar ));
 DATA(insert OID = 1244 (  byteain          PGUID 11 f t f 1 f 17 "0" 100 0 0 100  foo bar ));
@@ -524,6 +525,7 @@ DATA(insert OID = 696 (  char8regexne      PGUID 11 f t f 2 f 16 "411 25" 100 0
 DATA(insert OID = 699 (  char2regexeq      PGUID 11 f t f 2 f 16 "409 25" 100 0 0 100  foo bar ));
 
 /* OIDS 700 - 799 */
+
 DATA(insert OID = 1288 (  char16regexeq    PGUID 11 f t f 2 f 16 "19 25" 100 0 0 100  foo bar ));
 DATA(insert OID = 1289 (  char16regexne    PGUID 11 f t f 2 f 16 "19 25" 100 0 0 100  foo bar ));
 
@@ -534,13 +536,16 @@ DATA(insert OID = 715 (  oidsrand          PGUID 11 f t f 1 f 16 "23" 100 0 0 10
 DATA(insert OID = 716 (  oideqint4         PGUID 11 f t f 2 f 16 "26 23" 100 0 0 100  foo bar ));
 DATA(insert OID = 717 (  int4eqoid         PGUID 11 f t f 2 f 16 "23 26" 100 0 0 100  foo bar ));
 
-
 DATA(insert OID = 720 (  byteaGetSize     PGUID 11 f t f 1 f 23 "17" 100 0 0 100  foo bar ));
 DATA(insert OID = 721 (  byteaGetByte     PGUID 11 f t f 2 f 23 "17 23" 100 0 0 100  foo bar ));
 DATA(insert OID = 722 (  byteaSetByte     PGUID 11 f t f 3 f 17 "17 23 23" 100 0 0 100  foo bar ));
 DATA(insert OID = 723 (  byteaGetBit      PGUID 11 f t f 2 f 23 "17 23" 100 0 0 100  foo bar ));
 DATA(insert OID = 724 (  byteaSetBit      PGUID 11 f t f 3 f 17 "17 23 23" 100 0 0 100  foo bar ));
 
+DATA(insert OID = 725 (  dist_pl           PGUID 11 f t f 2 f 701 "600 654" 100 0 0 100  foo bar ));
+DATA(insert OID = 726 (  dist_lb           PGUID 11 f t f 2 f 701 "654 603" 100 0 0 100  foo bar ));
+DATA(insert OID = 727 (  dist_sl           PGUID 11 f t f 2 f 701 "601 654" 100 0 0 100  foo bar ));
+
 DATA(insert OID = 730 (  pqtest            PGUID 11 f t f 1 f 23 "25" 100 0 0 100  foo bar ));
 
 DATA(insert OID = 740 (  text_lt           PGUID 11 f t f 2 f 16 "25 25" 100 0 0 0  foo bar ));
@@ -587,6 +592,7 @@ DATA(insert OID = 781 (  gistrestrpos      PGUID 11 f t f 1 f 23 "0" 100 0 0 100
 DATA(insert OID = 782 (  gistbuild         PGUID 11 f t f 9 f 23 "0" 100 0 0 100  foo bar ));
 
 /* OIDS 800 - 899 */
+
 DATA(insert OID = 820 (  oidint2in        PGUID 11 f t f 1 f 810 "0" 100 0 0 100  foo bar));
 DATA(insert OID = 821 (  oidint2out       PGUID 11 f t f 1 f 19 "0" 100 0 0 100  foo bar));
 DATA(insert OID = 822 (  oidint2lt        PGUID 11 f t f 2 f 16 "810 810" 100 0 0 100  foo bar));
@@ -747,6 +753,7 @@ DATA(insert OID = 1091 (  date_ne          PGUID 11 f t f 2 f 16 "1082 1082" 100
 DATA(insert OID = 1092 (  date_cmp         PGUID 11 f t f 2 f 23 "1082 1082" 100 0 0 100  foo bar ));
 
 /* OIDS 1100 - 1199 */
+
 DATA(insert OID = 1102 (  time_lt          PGUID 11 f t f 2 f 16 "1083 1083" 100 0 0 100  foo bar ));
 DATA(insert OID = 1103 (  time_le          PGUID 11 f t f 2 f 16 "1083 1083" 100 0 0 100  foo bar ));
 DATA(insert OID = 1104 (  time_gt          PGUID 11 f t f 2 f 16 "1083 1083" 100 0 0 100  foo bar ));
@@ -806,6 +813,7 @@ DATA(insert OID = 1194 (  timespan_reltime   PGUID 11 f t f 1 f  703 "1186" 100
 /* reserve OIDs 1195-1199 for additional date/time conversion routines! tgl 97/03/19 */
 
 /* OIDS 1200 - 1299 */
+
 DATA(insert OID = 1200 (  int42reltime     PGUID 11 f t f 1 f 703 "21" 100 0 0 100  foo bar ));
 
 DATA(insert OID = 1290 (  char2icregexeq   PGUID 11 f t f 2 f 16 "409 25" 100 0 0 100  foo bar ));
@@ -826,6 +834,7 @@ DATA(insert OID = 1298 (  timestamp_out    PGUID 11 f t f 1 f 23 "0" 100 0 0 100
 DATA(insert OID = 1299 (  now              PGUID 11 f t f 0 f 1296 "0" 100 0 0 100  foo bar ));
 
 /* OIDS 1300 - 1399 */
+
 DATA(insert OID = 1306 (  timestampeq      PGUID 11 f t f 2 f 16 "1296 1296" 100 0 0 100  foo bar ));
 DATA(insert OID = 1307 (  timestampne      PGUID 11 f t f 2 f 16 "1296 1296" 100 0 0 100  foo bar ));
 DATA(insert OID = 1308 (  timestamplt      PGUID 11 f t f 2 f 16 "1296 1296" 100 0 0 100  foo bar ));
@@ -873,6 +882,7 @@ DATA(insert OID = 1392 (  isfinite     PGUID 14 f t f 1 f   16  "702" 100 0 0 10
 /* reserve OIDs 1370-1399 for additional date/time conversion routines! tgl 97/04/01 */
 
 /* OIDS 1400 - 1499 */
+
 DATA(insert OID = 1400 (  float        PGUID 14 f t f 1 f  701  "701" 100 0 0 100  "select $1" - ));
 DATA(insert OID = 1401 (  float        PGUID 14 f t f 1 f  701  "700" 100 0 0 100  "select ftod($1)" - ));
 DATA(insert OID = 1402 (  float4       PGUID 14 f t f 1 f  700  "700" 100 0 0 100  "select $1" - ));
@@ -880,6 +890,109 @@ DATA(insert OID = 1403 (  float4       PGUID 14 f t f 1 f  700  "701" 100 0 0 10
 DATA(insert OID = 1404 (  int          PGUID 14 f t f 1 f   23   "23" 100 0 0 100  "select $1" - ));
 DATA(insert OID = 1405 (  int2         PGUID 14 f t f 1 f   21   "21" 100 0 0 100  "select $1" - ));
 
+DATA(insert OID = 1421 (  box               PGUID 11 f t f 2 f 603 "600 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1422 (  box_add           PGUID 11 f t f 2 f 603 "603 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1423 (  box_sub           PGUID 11 f t f 2 f 603 "603 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1424 (  box_mul           PGUID 11 f t f 2 f 603 "603 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1425 (  box_div           PGUID 11 f t f 2 f 603 "603 600" 100 0 0 100  foo bar ));
+
+DATA(insert OID = 1430 (  path_isclosed     PGUID 11 f t f 1 f  16 "602" 100 0 0 100  foo bar ));
+DATA(insert OID = 1431 (  path_isopen       PGUID 11 f t f 1 f  16 "602" 100 0 0 100  foo bar ));
+DATA(insert OID = 1432 (  path_npoints      PGUID 11 f t f 1 f  23 "602" 100 0 0 100  foo bar ));
+DATA(insert OID = 1433 (  path_close        PGUID 11 f t f 1 f 602 "602" 100 0 0 100  foo bar ));
+DATA(insert OID = 1434 (  path_open         PGUID 11 f t f 1 f 602 "602" 100 0 0 100  foo bar ));
+DATA(insert OID = 1435 (  path_add          PGUID 11 f t f 2 f 602 "602 602" 100 0 0 100  foo bar ));
+DATA(insert OID = 1436 (  path_add_pt       PGUID 11 f t f 2 f 602 "602 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1437 (  path_sub_pt       PGUID 11 f t f 2 f 602 "602 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1438 (  path_mul_pt       PGUID 11 f t f 2 f 602 "602 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1439 (  path_div_pt       PGUID 11 f t f 2 f 602 "602 600" 100 0 0 100  foo bar ));
+
+DATA(insert OID = 1440 (  point             PGUID 11 f t f 2 f 600 "701 701" 100 0 0 100  foo bar ));
+DATA(insert OID = 1441 (  point_add         PGUID 11 f t f 2 f 600 "600 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1442 (  point_sub         PGUID 11 f t f 2 f 600 "600 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1443 (  point_mul         PGUID 11 f t f 2 f 600 "600 600" 100 0 0 100  foo bar ));
+DATA(insert OID = 1444 (  point_div         PGUID 11 f t f 2 f 600 "600 600" 100 0 0 100  foo bar ));
+
+DATA(insert OID = 1445 (  poly_npoints      PGUID 11 f t f 1 f  23 "604" 100 0 0 100  foo bar ));
+DATA(insert OID = 1446 (  poly_box          PGUID 11 f t f 1 f 603 "604" 100 0 0 100  foo bar ));
+DATA(insert OID = 1447 (  poly_path         PGUID 11 f t f 1 f 602 "604" 100 0 0 100  foo bar ));
+DATA(insert OID = 1448 (  box_poly          PGUID 11 f t f 1 f 604 "603" 100 0 0 100  foo bar ));
+DATA(insert OID = 1449 (  path_poly         PGUID 11 f t f 1 f 604 "602" 100 0 0 100  foo bar ));
+
+DATA(insert OID = 1450 (  circle_in         PGUID 11 f t f 1 f 718 "0" 100 0 1 0  foo bar ));
+DATA(insert OID = 1451 (  circle_out        PGUID 11 f t f 1 f  23  "0" 100 0 1 0  foo bar ));
+DATA(insert OID = 1452 (  circle_same       PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1453 (  circle_contain    PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1454 (  circle_left       PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1455 (  circle_overleft   PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1456 (  circle_overright  PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1457 (  circle_right      PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1458 (  circle_contained  PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1459 (  circle_overlap    PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1460 (  circle_below      PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1461 (  circle_above      PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1462 (  circle_eq         PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1463 (  circle_ne         PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1464 (  circle_lt         PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1465 (  circle_gt         PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1466 (  circle_le         PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1467 (  circle_ge         PGUID 11 f t f 2 f  16 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1468 (  circle_area       PGUID 11 f t f 1 f 701 "718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1469 (  circle_diameter   PGUID 11 f t f 1 f 701 "718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1470 (  circle_radius     PGUID 11 f t f 1 f 701 "718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1471 (  circle_distance   PGUID 11 f t f 2 f 701 "718 718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1472 (  circle_center     PGUID 11 f t f 1 f 600 "718" 100 0 1 0  foo bar ));
+DATA(insert OID = 1473 (  circle            PGUID 11 f t f 2 f 718 "600 701" 100 0 1 0  foo bar ));
+DATA(insert OID = 1474 (  poly_circle       PGUID 11 f t f 1 f 718 "604" 100 0 1 0  foo bar ));
+DATA(insert OID = 1475 (  circle_poly       PGUID 11 f t f 2 f 604 "23 718" 100 0 1 0  foo bar ));
+
+DATA(insert OID = 1530 (  point             PGUID 14 f t f 2 f 600 "601 601" 100 0 0 100  "select lseg_interpt($1, $2)" - ));
+DATA(insert OID = 1531 (  point             PGUID 14 f t f 1 f 600 "718" 100 0 0 100  "select circle_center($1)" - ));
+DATA(insert OID = 1532 (  isvertical        PGUID 14 f t f 2 f  16 "600 600" 100 0 0 100  "select point_vert($1, $2)" - ));
+DATA(insert OID = 1533 (  ishorizonal       PGUID 14 f t f 2 f  16 "600 600" 100 0 0 100  "select point_horiz($1, $2)" - ));
+DATA(insert OID = 1534 (  slope             PGUID 14 f t f 2 f 701 "600 600" 100 0 0 100  "select point_slope($1, $2)" - ));
+
+DATA(insert OID = 1540 (  lseg              PGUID 14 f t f 2 f 601 "600 600" 100 0 0 100  "select lseg_construct($1, $2)" - ));
+DATA(insert OID = 1541 (  lseg              PGUID 14 f t f 1 f 601 "603" 100 0 0 100  "select box_diagonal($1)" - ));
+DATA(insert OID = 1542 (  isparallel        PGUID 14 f t f 2 f  16 "601 601" 100 0 0 100  "select lseg_parallel($1, $2)" - ));
+DATA(insert OID = 1543 (  isperpendicular   PGUID 14 f t f 2 f  16 "601 601" 100 0 0 100  "select lseg_perp($1, $2)" - ));
+DATA(insert OID = 1544 (  isvertical        PGUID 14 f t f 1 f  16 "601" 100 0 0 100  "select lseg_vertical($1)" - ));
+DATA(insert OID = 1545 (  ishorizontal      PGUID 14 f t f 1 f  16 "601" 100 0 0 100  "select lseg_horizontal($1)" - ));
+
+/* XXX "length" for boxes is different than "length" for paths, so use "width" for boxes instead.
+ * should go back into code and change subroutine name from "box_length" to "box_width".
+ * pclose and popen might better be named close and open, but that crashes initdb.
+ * - tgl 97/04/20
+ */
+
+DATA(insert OID = 1550 (  path              PGUID 14 f t f 1 f 602 "604" 100 0 0 100  "select poly_path($1)" - ));
+DATA(insert OID = 1551 (  length            PGUID 14 f t f 1 f 701 "602" 100 0 1 0  "select path_length($1)" - ));
+DATA(insert OID = 1552 (  points            PGUID 14 f t f 1 f  23 "602" 100 0 0 100  "select path_npoints($1)" - ));
+DATA(insert OID = 1553 (  pclose            PGUID 14 f t f 1 f 602 "602" 100 0 0 100  "select path_close($1)" - ));
+DATA(insert OID = 1554 (  popen             PGUID 14 f t f 1 f 602 "602" 100 0 0 100  "select path_open($1)" - ));
+DATA(insert OID = 1555 (  isopen            PGUID 14 f t f 1 f  16 "602" 100 0 0 100  "select path_isopen($1)" - ));
+DATA(insert OID = 1555 (  isclosed          PGUID 14 f t f 1 f  16 "602" 100 0 0 100  "select path_isclosed($1)" - ));
+
+DATA(insert OID = 1560 (  box               PGUID 14 f t f 2 f 603 "603 603" 100 0 0 100  "select box_intersect($1, $2)" - ));
+DATA(insert OID = 1561 (  box               PGUID 14 f t f 1 f 603 "604" 100 0 0 100  "select poly_box($1)" - ));
+DATA(insert OID = 1562 (  width             PGUID 14 f t f 1 f 701 "603" 100 0 0 100  "select box_length($1)" - ));
+DATA(insert OID = 1563 (  height            PGUID 14 f t f 1 f 701 "603" 100 0 0 100  "select box_height($1)" - ));
+DATA(insert OID = 1564 (  center            PGUID 14 f t f 1 f 600 "603" 100 0 0 100  "select box_center($1)" - ));
+DATA(insert OID = 1565 (  area              PGUID 14 f t f 1 f 701 "603" 100 0 0 100  "select box_area($1)" - ));
+
+DATA(insert OID = 1570 (  polygon           PGUID 14 f t f 1 f 604 "602" 100 0 0 100  "select path_poly($1)" - ));
+DATA(insert OID = 1571 (  polygon           PGUID 14 f t f 1 f 604 "603" 100 0 0 100  "select box_poly($1)" - ));
+DATA(insert OID = 1572 (  polygon           PGUID 14 f t f 2 f 604 "23 718" 100 0 0 100  "select circle_poly($1, $2)" - ));
+DATA(insert OID = 1573 (  polygon           PGUID 14 f t f 1 f 604 "718" 100 0 0 100  "select circle_poly(12, $1)" - ));
+DATA(insert OID = 1574 (  points            PGUID 14 f t f 1 f  23 "604" 100 0 0 100  "select poly_npoints($1)" - ));
+DATA(insert OID = 1575 (  center            PGUID 14 f t f 1 f 600 "604" 100 0 0 100  "select poly_center($1)" - ));
+
+DATA(insert OID = 1580 (  circle            PGUID 14 f t f 1 f 701 "604" 100 0 0 100  "select poly_circle($1)" - ));
+DATA(insert OID = 1581 (  center            PGUID 14 f t f 1 f 600 "718" 100 0 0 100  "select circle_center($1)" - ));
+DATA(insert OID = 1582 (  radius            PGUID 14 f t f 1 f 701 "718" 100 0 0 100  "select circle_radius($1)" - ));
+DATA(insert OID = 1583 (  diameter          PGUID 14 f t f 1 f 701 "718" 100 0 0 100  "select circle_diameter($1)" - ));
+DATA(insert OID = 1584 (  area              PGUID 14 f t f 1 f 701 "718" 100 0 0 100  "select circle_area($1)" - ));
+
 /* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
 DATA(insert OID =  870 (  lower        PGUID 11 f t f 1 f 25 "25" 100 0 0 100  foo bar ));
 DATA(insert OID =  871 (  upper        PGUID 11 f t f 1 f 25 "25" 100 0 0 100  foo bar ));
index f5a59fffd42658e9ba7d528752b02720bb2c087f..ccd01349eac43b7124e8d1b5daa41fd8b01bcbe1 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.10 1997/04/15 17:41:19 scrappy Exp $
+ * $Id: pg_type.h,v 1.11 1997/04/22 17:32:26 scrappy Exp $
  *
  * NOTES
  *    the genbki.sh script reads this file and generates .bki
@@ -220,7 +220,10 @@ DATA(insert OID = 601 (  lseg      PGUID 32  48 f b t \054 0 600 lseg_in lseg_ou
 DATA(insert OID = 602 (  path      PGUID -1  -1 f b t \054 0 600 path_in path_out path_in path_out d _null_ ));
 DATA(insert OID = 603 (  box       PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d _null_ ));
 DATA(insert OID = 604 (  polygon   PGUID -1  -1 f b t \054 0  -1 poly_in poly_out poly_in poly_out d _null_ ));
-DATA(insert OID = 605 (  filename  PGUID 256 -1 f b t \054 0 18 filename_in filename_out filename_in filename_out i _null_ ));
+DATA(insert OID = 605 (  filename  PGUID 256 -1 f b t \054 0  18 filename_in filename_out filename_in filename_out i _null_ ));
+
+DATA(insert OID = 628 (  line      PGUID 32  48 f b t \054 0 701 line_in line_out line_in line_out d _null_ ));
+DATA(insert OID = 629 (  _line     PGUID  -1 -1 f b t \054 0 628 array_in array_out array_in array_out d _null_ ));
 
 /* OIDS 700 - 799 */
 
@@ -234,8 +237,9 @@ DATA(insert OID = 704 (  tinterval PGUID 12  47 f b t \054 0   0 tintervalin tin
 DATA(insert OID = 705 (  unknown   PGUID -1  -1 f b t \054 0   18 textin textout textin textout i _null_ ));
 #define UNKNOWNOID     705
 
-DATA(insert OID = 790 (  money     PGUID  4  47 f b t \054 0    0 cash_in cash_out cash_in cash_out i _null_ ));
-#define CASHOID        790
+DATA(insert OID = 718 (  circle    PGUID  24 47 f b t \054 0    0 circle_in circle_out circle_in circle_out d _null_ ));
+DATA(insert OID = 719 (  _circle   PGUID  -1 -1 f b t \054 0  718 array_in array_out array_in array_out i _null_ ));
+DATA(insert OID = 790 (  money     PGUID   4 24 f b t \054 0    0 cash_in cash_out cash_in cash_out i _null_ ));
 DATA(insert OID = 791 (  _money    PGUID  -1 -1 f b t \054 0  790 array_in array_out array_in array_out i _null_ ));
 
 /* OIDS 800 - 899 */
index d9f156d422ca6812f0fc03b622397d89f93ed492..cdd9f6895a687381f5f89e680d0022ee8e2821e3 100644 (file)
@@ -1,17 +1,18 @@
 /*-------------------------------------------------------------------------
  *
- * geo_decls.h--
- *    Declarations for various 2D constructs.
+ * geo_decls.h - Declarations for various 2D constructs.
  *
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: geo_decls.h,v 1.1 1997/03/14 23:33:27 scrappy Exp $
+ * $Id: geo_decls.h,v 1.2 1997/04/22 17:32:41 scrappy Exp $
  *
  * NOTE
  *    These routines do *not* use the float types from adt/.
  *
  *    XXX These routines were not written by a numerical analyst.
+ *    XXX I have made some attempt to flesh out the operators
+ *     and data types. There are still some more to do. - tgl 97/04/19
  *
  *-------------------------------------------------------------------------
  */
 /*#ifndef FmgrIncluded -- seems like always included. (it's FMgrIncluded) AY */
 
 /*--------------------------------------------------------------------
- *     Useful floating point utilities and constants.
+ * Useful floating point utilities and constants.
  *-------------------------------------------------------------------*/
 
 
 #define        EPSILON                 1.0E-06
 
+#ifdef EPSILON
 #define        FPzero(A)               (fabs(A) <= EPSILON)
 #define        FPeq(A,B)               (fabs((A) - (B)) <= EPSILON)
 #define        FPlt(A,B)               ((B) - (A) > EPSILON)
 #define        FPle(A,B)               ((A) - (B) <= EPSILON)
 #define        FPgt(A,B)               ((A) - (B) > EPSILON)
 #define        FPge(A,B)               ((B) - (A) <= EPSILON)
+#else
+#define        FPzero(A)               (A == 0)
+#define        FPeq(A,B)               (A == B)
+#define        FPlt(A,B)               (A < B)
+#define        FPle(A,B)               (A <= B)
+#define        FPgt(A,B)               (A > B)
+#define        FPge(A,B)               (A >= B)
+#endif
 
 #define        HYPOT(A, B)             sqrt((A) * (A) + (B) * (B))
 
 /*--------------------------------------------------------------------
- *     Memory management.
+ * Memory management.
  *-------------------------------------------------------------------*/
 
 #define        PALLOC(SIZE)            palloc(SIZE)
@@ -49,7 +59,7 @@
 /*#endif !FmgrIncluded */
 
 /*---------------------------------------------------------------------
- *     Point   -       (x,y)
+ * Point - (x,y)
  *-------------------------------------------------------------------*/
 typedef struct {
        double  x, y;
@@ -57,7 +67,7 @@ typedef struct {
 
 
 /*---------------------------------------------------------------------
- *     LSEG    -       A straight line, specified by endpoints.
+ * LSEG        - A straight line, specified by endpoints.
  *-------------------------------------------------------------------*/
 typedef        struct {
        Point   p[2];
@@ -67,24 +77,24 @@ typedef     struct {
 
 
 /*---------------------------------------------------------------------
- *     PATH    -       Specified by vertex points.
+ * PATH        - Specified by vertex points.
  *-------------------------------------------------------------------*/
 typedef        struct {
-       int32   length; /* XXX varlena */
+       int32   size;   /* XXX varlena */
        int32   npts;
        int32   closed; /* is this a closed polygon? */
        int32   dummy;  /* padding to make it double align */
-       Point   p[1];   /* variable length array of POINTs */
+       Point   p[0];   /* variable length array of POINTs */
 } PATH;
 
 
 /*---------------------------------------------------------------------
- *     LINE    -       Specified by its general equation (Ax+By+C=0).
- *                     If there is a y-intercept, it is C, which
- *                      incidentally gives a freebie point on the line
- *                      (if B=0, then C is the x-intercept).
- *                     Slope m is precalculated to save time; if
- *                      the line is not vertical, m == A.
+ * LINE        - Specified by its general equation (Ax+By+C=0).
+ *     If there is a y-intercept, it is C, which
+ *      incidentally gives a freebie point on the line
+ *      (if B=0, then C is the x-intercept).
+ *     Slope m is precalculated to save time; if
+ *      the line is not vertical, m == A.
  *-------------------------------------------------------------------*/
 typedef struct {
        double  A, B, C;
@@ -93,25 +103,32 @@ typedef struct {
 
 
 /*---------------------------------------------------------------------
- *     BOX     -       Specified by two corner points, which are
- *                      sorted to save calculation time later.
+ * BOX - Specified by two corner points, which are
+ *      sorted to save calculation time later.
  *-------------------------------------------------------------------*/
 typedef struct {
-       double  xh, yh, xl, yl;         /* high and low coords */
+       Point   high, low;      /* corner POINTs */
 } BOX;
 
 /*---------------------------------------------------------------------
- *  POLYGON - Specified by an array of doubles defining the points, 
- *                       keeping the number of points and the bounding box for 
- *                       speed purposes.
+ * POLYGON - Specified by an array of doubles defining the points, 
+ *     keeping the number of points and the bounding box for 
+ *     speed purposes.
  *-------------------------------------------------------------------*/
 typedef struct {
        int32 size;     /* XXX varlena */
        int32 npts;
        BOX boundbox;
-       char pts[1];
+       Point p[0];     /* variable length array of POINTs */
 } POLYGON;
 
+/*---------------------------------------------------------------------
+ * CIRCLE - Specified by a center point and radius.
+ *-------------------------------------------------------------------*/
+typedef struct {
+    Point       center;
+    double      radius;
+} CIRCLE;
 
 /* 
  * in geo_ops.h
@@ -121,81 +138,115 @@ extern char *box_out(BOX *box);
 extern BOX *box_construct(double x1, double x2, double y1, double y2);
 extern BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2);
 extern BOX *box_copy(BOX *box);
-extern long box_same(BOX *box1, BOX *box2);
-extern long box_overlap(BOX *box1, BOX *box2);
-extern long box_overleft(BOX *box1, BOX *box2);
-extern long box_left(BOX *box1, BOX *box2);
-extern long box_right(BOX *box1, BOX *box2);
-extern long box_overright(BOX *box1, BOX *box2);
-extern long box_contained(BOX *box1, BOX *box2);
-extern long box_contain(BOX *box1, BOX *box2);
-extern long box_below(BOX *box1, BOX *box2);
-extern long box_above(BOX *box1, BOX *box2);
-extern long box_lt(BOX *box1, BOX *box2);
-extern long box_gt(BOX *box1, BOX *box2);
-extern long box_eq(BOX *box1, BOX *box2);
-extern long box_le(BOX *box1, BOX *box2);
-extern long box_ge(BOX *box1, BOX *box2);
+extern bool box_same(BOX *box1, BOX *box2);
+extern bool box_overlap(BOX *box1, BOX *box2);
+extern bool box_overleft(BOX *box1, BOX *box2);
+extern bool box_left(BOX *box1, BOX *box2);
+extern bool box_right(BOX *box1, BOX *box2);
+extern bool box_overright(BOX *box1, BOX *box2);
+extern bool box_contained(BOX *box1, BOX *box2);
+extern bool box_contain(BOX *box1, BOX *box2);
+extern bool box_below(BOX *box1, BOX *box2);
+extern bool box_above(BOX *box1, BOX *box2);
+extern bool box_lt(BOX *box1, BOX *box2);
+extern bool box_gt(BOX *box1, BOX *box2);
+extern bool box_eq(BOX *box1, BOX *box2);
+extern bool box_le(BOX *box1, BOX *box2);
+extern bool box_ge(BOX *box1, BOX *box2);
+extern Point *box_center(BOX *box);
 extern double *box_area(BOX *box);
 extern double *box_length(BOX *box);
 extern double *box_height(BOX *box);
 extern double *box_distance(BOX *box1, BOX *box2);
 extern Point *box_center(BOX *box);
+extern BOX *box_intersect(BOX *box1, BOX *box2);
+extern LSEG *box_diagonal(BOX *box);
+
+/* private routines */
 extern double box_ar(BOX *box);
 extern double box_ln(BOX *box);
 extern double box_ht(BOX *box);
 extern double box_dt(BOX *box1, BOX *box2);
-extern BOX *box_intersect(BOX *box1, BOX *box2);
-extern LSEG *box_diagonal(BOX *box);
+
+extern BOX *box(Point *p1, Point *p2);
+extern BOX *box_add(BOX *box, Point *p);
+extern BOX *box_sub(BOX *box, Point *p);
+extern BOX *box_mul(BOX *box, Point *p);
+extern BOX *box_div(BOX *box, Point *p);
+
 extern LINE *line_construct_pm(Point *pt, double m);
 extern LINE *line_construct_pp(Point *pt1, Point *pt2);
-extern long line_intersect(LINE *l1, LINE *l2);
-extern long line_parallel(LINE *l1, LINE *l2);
-extern long line_perp(LINE *l1, LINE *l2);
-extern long line_vertical(LINE *line);
-extern long line_horizontal(LINE *line);
-extern long line_eq(LINE *l1, LINE *l2);
+extern bool line_intersect(LINE *l1, LINE *l2);
+extern bool line_parallel(LINE *l1, LINE *l2);
+extern bool line_perp(LINE *l1, LINE *l2);
+extern bool line_vertical(LINE *line);
+extern bool line_horizontal(LINE *line);
+extern bool line_eq(LINE *l1, LINE *l2);
 extern double *line_distance(LINE *l1, LINE *l2);
 extern Point *line_interpt(LINE *l1, LINE *l2);
+
 extern PATH *path_in(char *str);
 extern char *path_out(PATH *path);
-extern long path_n_lt(PATH *p1, PATH *p2);
-extern long path_n_gt(PATH *p1, PATH *p2);
-extern long path_n_eq(PATH *p1, PATH *p2);
-extern long path_n_le(PATH *p1, PATH *p2);
-extern long path_n_ge(PATH *p1, PATH *p2);
-extern long path_inter(PATH *p1, PATH *p2);
+extern bool path_n_lt(PATH *p1, PATH *p2);
+extern bool path_n_gt(PATH *p1, PATH *p2);
+extern bool path_n_eq(PATH *p1, PATH *p2);
+extern bool path_n_le(PATH *p1, PATH *p2);
+extern bool path_n_ge(PATH *p1, PATH *p2);
+extern bool path_inter(PATH *p1, PATH *p2);
 extern double *path_distance(PATH *p1, PATH *p2);
 extern double *path_length(PATH *path);
+
+/* private routines */
 extern double path_ln(PATH *path);
+
+extern bool path_isclosed(PATH *path);
+extern bool path_isopen(PATH *path);
+extern int4 path_npoints(PATH *path);
+
+extern PATH *path_close(PATH *path);
+extern PATH *path_open(PATH *path);
+extern PATH *path_add(PATH *p1, PATH *p2);
+extern PATH *path_add_pt(PATH *path, Point *point);
+extern PATH *path_sub_pt(PATH *path, Point *point);
+extern PATH *path_mul_pt(PATH *path, Point *point);
+extern PATH *path_div_pt(PATH *path, Point *point);
+
+extern POLYGON *path_poly(PATH *path);
+
 extern Point *point_in(char *str);
 extern char *point_out(Point *pt);
 extern Point *point_construct(double x, double y);
 extern Point *point_copy(Point *pt);
-extern long point_left(Point *pt1, Point *pt2);
-extern long point_right(Point *pt1, Point *pt2);
-extern long point_above(Point *pt1, Point *pt2);
-extern long point_below(Point *pt1, Point *pt2);
-extern long point_vert(Point *pt1, Point *pt2);
-extern long point_horiz(Point *pt1, Point *pt2);
-extern long point_eq(Point *pt1, Point *pt2);
-extern long pointdist(Point *p1, Point *p2);
+extern bool point_left(Point *pt1, Point *pt2);
+extern bool point_right(Point *pt1, Point *pt2);
+extern bool point_above(Point *pt1, Point *pt2);
+extern bool point_below(Point *pt1, Point *pt2);
+extern bool point_vert(Point *pt1, Point *pt2);
+extern bool point_horiz(Point *pt1, Point *pt2);
+extern bool point_eq(Point *pt1, Point *pt2);
+extern int32 pointdist(Point *p1, Point *p2);
 extern double *point_distance(Point *pt1, Point *pt2);
-extern double point_dt(Point *pt1, Point *pt2);
 extern double *point_slope(Point *pt1, Point *pt2);
+
+/* private routines */
+extern double point_dt(Point *pt1, Point *pt2);
 extern double point_sl(Point *pt1, Point *pt2);
+
+extern Point *point(float8 *x, float8 *y);
+extern Point *point_add(Point *p1, Point *p2);
+extern Point *point_sub(Point *p1, Point *p2);
+extern Point *point_mul(Point *p1, Point *p2);
+extern Point *point_div(Point *p1, Point *p2);
+
 extern LSEG *lseg_in(char *str);
 extern char *lseg_out(LSEG *ls);
-extern LSEG *lseg_construct(Point *pt1, Point *pt2);
-extern void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
-extern long lseg_intersect(LSEG *l1, LSEG *l2);
-extern long lseg_parallel(LSEG *l1, LSEG *l2);
-extern long lseg_perp(LSEG *l1, LSEG *l2);
-extern long lseg_vertical(LSEG *lseg);
-extern long lseg_horizontal(LSEG *lseg);
-extern long lseg_eq(LSEG *l1, LSEG *l2);
+extern bool lseg_intersect(LSEG *l1, LSEG *l2);
+extern bool lseg_parallel(LSEG *l1, LSEG *l2);
+extern bool lseg_perp(LSEG *l1, LSEG *l2);
+extern bool lseg_vertical(LSEG *lseg);
+extern bool lseg_horizontal(LSEG *lseg);
+extern bool lseg_eq(LSEG *l1, LSEG *l2);
 extern double *lseg_distance(LSEG *l1, LSEG *l2);
-extern double lseg_dt(LSEG *l1, LSEG *l2);
 extern Point *lseg_interpt(LSEG *l1, LSEG *l2);
 extern double *dist_pl(Point *pt, LINE *line);
 extern double *dist_ps(Point *pt, LSEG *lseg);
@@ -211,29 +262,73 @@ extern Point *close_pb(Point *pt, BOX *box);
 extern Point *close_sl(LSEG *lseg, LINE *line);
 extern Point *close_sb(LSEG *lseg, BOX *box);
 extern Point *close_lb(LINE *line, BOX *box);
-extern long on_pl(Point *pt, LINE *line);
-extern long on_ps(Point *pt, LSEG *lseg);
-extern long on_pb(Point *pt, BOX *box);
-extern long on_ppath(Point *pt, PATH *path);
-extern long on_sl(LSEG *lseg, LINE *line);
-extern long on_sb(LSEG *lseg, BOX *box);
-extern long inter_sl(LSEG *lseg, LINE *line);
-extern long inter_sb(LSEG *lseg, BOX *box);
-extern long inter_lb(LINE *line, BOX *box);
+extern bool on_pl(Point *pt, LINE *line);
+extern bool on_ps(Point *pt, LSEG *lseg);
+extern bool on_pb(Point *pt, BOX *box);
+extern bool on_ppath(Point *pt, PATH *path);
+extern bool on_sl(LSEG *lseg, LINE *line);
+extern bool on_sb(LSEG *lseg, BOX *box);
+extern bool inter_sl(LSEG *lseg, LINE *line);
+extern bool inter_sb(LSEG *lseg, BOX *box);
+extern bool inter_lb(LINE *line, BOX *box);
+
+/* private routines */
+extern LSEG *lseg_construct(Point *pt1, Point *pt2);
+extern void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
+extern double lseg_dt(LSEG *l1, LSEG *l2);
 extern void make_bound_box(POLYGON *poly);
+
 extern POLYGON *poly_in(char *s);
-extern long poly_pt_count(char *s, char delim);
 extern char *poly_out(POLYGON *poly);
-extern double poly_max(double *coords, int ncoords);
-extern double poly_min(double *coords, int ncoords);
-extern long poly_left(POLYGON *polya, POLYGON *polyb);
-extern long poly_overleft(POLYGON *polya, POLYGON *polyb);
-extern long poly_right(POLYGON *polya, POLYGON *polyb);
-extern long poly_overright(POLYGON *polya, POLYGON *polyb);
-extern long poly_same(POLYGON *polya, POLYGON *polyb);
-extern long poly_overlap(POLYGON *polya, POLYGON *polyb);
-extern long poly_contain(POLYGON *polya, POLYGON *polyb);
-extern long poly_contained(POLYGON *polya, POLYGON *polyb);
+extern bool poly_left(POLYGON *polya, POLYGON *polyb);
+extern bool poly_overleft(POLYGON *polya, POLYGON *polyb);
+extern bool poly_right(POLYGON *polya, POLYGON *polyb);
+extern bool poly_overright(POLYGON *polya, POLYGON *polyb);
+extern bool poly_same(POLYGON *polya, POLYGON *polyb);
+extern bool poly_overlap(POLYGON *polya, POLYGON *polyb);
+extern bool poly_contain(POLYGON *polya, POLYGON *polyb);
+extern bool poly_contained(POLYGON *polya, POLYGON *polyb);
+
+extern int4 poly_npoints(POLYGON *poly);
+extern BOX *poly_box(POLYGON *poly);
+extern PATH *poly_path(POLYGON *poly);
+extern POLYGON *box_poly(BOX *box);
+
+extern CIRCLE *circle_in(char *str);
+extern char *circle_out(CIRCLE *circle);
+extern bool circle_same(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_overlap(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_overleft(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_left(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_right(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_overright(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_contained(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_contain(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_below(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_above(CIRCLE *circle1, CIRCLE *circle2);
+
+extern bool circle_eq(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_ne(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_lt(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_gt(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_le(CIRCLE *circle1, CIRCLE *circle2);
+extern bool circle_ge(CIRCLE *circle1, CIRCLE *circle2);
+extern CIRCLE *circle_add_pt(CIRCLE *circle, Point *point);
+extern CIRCLE *circle_sub_pt(CIRCLE *circle, Point *point);
+extern CIRCLE *circle_mul_pt(CIRCLE *circle, Point *point);
+extern CIRCLE *circle_div_pt(CIRCLE *circle, Point *point);
+extern double *circle_area(CIRCLE *circle);
+extern double *circle_diameter(CIRCLE *circle);
+extern double *circle_radius(CIRCLE *circle);
+extern double *circle_distance(CIRCLE *circle1, CIRCLE *circle2);
+extern Point *circle_center(CIRCLE *circle);
+extern CIRCLE *circle(Point *center, float8 *radius);
+extern CIRCLE *poly_circle(POLYGON *poly);
+extern POLYGON *circle_poly(int npts, CIRCLE *circle);
+
+/* private routines */
+extern double circle_ar(CIRCLE *circle);
+extern double circle_dt(CIRCLE *circle1, CIRCLE *circle2);
 
 /* geo_selfuncs.c */
 extern float64 areasel(Oid opid, Oid relid, AttrNumber attno, 
@@ -247,6 +342,6 @@ extern float64 leftjoinsel(Oid opid, Oid relid, AttrNumber attno,
 extern float64 contsel(Oid opid, Oid relid, AttrNumber attno,
        char *value, int32 flag);
 extern float64 contjoinsel(Oid opid, Oid relid, AttrNumber attno,
-           char *value, int32 flag);
+       char *value, int32 flag);
 
 #endif /* GEO_DECLS_H */
index c45e48a839633928d85d8ca8c6dfc1a725e2a14b..cc9217826d2524ceece702b54e75d7b9b7c1cdf1 100644 (file)
@@ -6,8 +6,8 @@ QUERY: CREATE OPERATOR ## (
 );
 QUERY: CREATE OPERATOR <% (
    leftarg = point,
-   rightarg = circle,
-   procedure = pt_in_circle,
+   rightarg = widget,
+   procedure = pt_in_widget,
    commutator = >=%
 );
 QUERY: CREATE OPERATOR @#@ (
index 7919b01e37b0a907ed442d928469ce519dd4076d..104a9eb5b8e5ca349e17c8458f4e4901a120be85 100644 (file)
@@ -1,7 +1,7 @@
-QUERY: CREATE TYPE circle (
+QUERY: CREATE TYPE widget (
    internallength = 24,
-   input = circle_in,
-   output = circle_out,
+   input = widget_in,
+   output = widget_out,
    alignment = double
 );
 QUERY: CREATE TYPE city_budget (
index 4466bd91874d877a78ab413702762029a9a0e189..5bc297a346baf6be90ea7e4d57e9b6ade16bd529 100644 (file)
@@ -3357,20 +3357,20 @@ QUERY: DROP FUNCTION hobbies(person);
 QUERY: DROP FUNCTION hobby_construct(text,text);
 QUERY: DROP FUNCTION equipment(hobbies_r);
 QUERY: DROP FUNCTION user_relns();
-QUERY: DROP FUNCTION circle_in(opaque);
-QUERY: DROP FUNCTION circle_out(opaque);
-QUERY: DROP FUNCTION pt_in_circle(point,circle);
+QUERY: DROP FUNCTION widget_in(opaque);
+QUERY: DROP FUNCTION widget_out(opaque);
+QUERY: DROP FUNCTION pt_in_widget(point,widget);
 QUERY: DROP FUNCTION overpaid(emp);
 QUERY: DROP FUNCTION boxarea(box);
 QUERY: DROP FUNCTION interpt_pp(path,path);
 QUERY: DROP FUNCTION reverse_c16(char16);
 QUERY: DROP OPERATOR ## (path, path);
-QUERY: DROP OPERATOR <% (point, circle);
+QUERY: DROP OPERATOR <% (point, widget);
 QUERY: DROP OPERATOR @#@ (none, int4);
 QUERY: DROP OPERATOR #@# (int4, none);
 QUERY: DROP OPERATOR #%# (int4, none);
 QUERY: DROP TYPE city_budget;
-QUERY: DROP TYPE circle;
+QUERY: DROP TYPE widget;
 QUERY: DROP AGGREGATE newavg;
 QUERY: DROP AGGREGATE newsum;
 QUERY: DROP AGGREGATE newcnt;
index fc944c4e1d913a7c654730294f886e44d189e792..602f0ca4e3e97b0e37cc17a565322c1acf9b8049 100644 (file)
@@ -3,12 +3,12 @@
 --
 --
 
-CREATE FUNCTION circle_in(opaque)
-   RETURNS circle
+CREATE FUNCTION widget_in(opaque)
+   RETURNS widget
    AS '_OBJWD_/regress_DLSUFFIX_'
    LANGUAGE 'c';
 
-CREATE FUNCTION circle_out(opaque)
+CREATE FUNCTION widget_out(opaque)
    RETURNS opaque
    AS '_OBJWD_/regress_DLSUFFIX_'
    LANGUAGE 'c';
@@ -42,7 +42,7 @@ CREATE FUNCTION user_relns()
              relkind <> ''i'' '
    LANGUAGE 'sql';
 
-CREATE FUNCTION pt_in_circle(point, circle)
+CREATE FUNCTION pt_in_widget(point, widget)
    RETURNS int4
    AS '_OBJWD_/regress_DLSUFFIX_'
    LANGUAGE 'c';
index 28f04d89558dc71e7d179c68dce32457b0c591a4..8eb70daf3f078b95f7cbcc6757afa9ff281c656c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.5 1997/03/14 23:34:16 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.6 1997/04/22 17:33:00 scrappy Exp $
  */
 
 #include <float.h>             /* faked on sunos */
@@ -103,22 +103,19 @@ poly2path(poly)
 {
     int i;
     char *output = (char *)PALLOC(2*(P_MAXDIG + 1)*poly->npts + 64);
-    char *outptr = output;
-    double *xp, *yp;
+    char buf[2*(P_MAXDIG)+20];
 
-    sprintf(outptr, "(1, %*d", P_MAXDIG, poly->npts);
-    xp = (double *) poly->pts;
-    yp = (double *) (poly->pts + (poly->npts * sizeof(double *)));
+    sprintf(output, "(1, %*d", P_MAXDIG, poly->npts);
 
-    for (i=1; i<poly->npts; i++,xp++,yp++)
+    for (i=0; i<poly->npts; i++)
      {
-        sprintf(outptr, ",%*g,%*g", P_MAXDIG, *xp, P_MAXDIG, *yp);
-        outptr += 2*(P_MAXDIG + 1);
+        sprintf(buf, ",%*g,%*g", P_MAXDIG, poly->p[i].x, P_MAXDIG, poly->p[i].y);
+        strcat(output, buf);
      }
 
-    *outptr++ = RDELIM;
-    *outptr = '\0';
-    return(path_in(outptr));
+    sprintf(buf, "%c", RDELIM);
+    strcat(output, buf);
+    return(path_in(output));
 }
 
 /* return the point where two paths intersect.  Assumes that they do. */
@@ -176,24 +173,29 @@ char overpaid(tuple)
     return(salary > 699);
 }
 
+/* New type "widget"
+ * This used to be "circle", but I added circle to builtins,
+ *  so needed to make sure the names do not collide. - tgl 97/04/21
+ */
+
 typedef struct {
        Point   center;
        double  radius;
-} CIRCLE;
+} WIDGET;
 
-extern CIRCLE *circle_in (char *str);
-extern char *circle_out (CIRCLE *circle);
-extern int pt_in_circle (Point *point, CIRCLE *circle);
+extern WIDGET *widget_in (char *str);
+extern char *widget_out (WIDGET *widget);
+extern int pt_in_widget (Point *point, WIDGET *widget);
 
 #define NARGS  3
 
-CIRCLE *
-circle_in(str)
+WIDGET *
+widget_in(str)
 char   *str;
 {
        char    *p, *coord[NARGS], buf2[1000];
        int     i;
-       CIRCLE  *result;
+       WIDGET  *result;
 
        if (str == NULL)
                return(NULL);
@@ -202,39 +204,39 @@ char      *str;
                        coord[i++] = p + 1;
        if (i < NARGS - 1)
                return(NULL);
-       result = (CIRCLE *) palloc(sizeof(CIRCLE));
+       result = (WIDGET *) palloc(sizeof(WIDGET));
        result->center.x = atof(coord[0]);
        result->center.y = atof(coord[1]);
        result->radius = atof(coord[2]);
 
-       sprintf(buf2, "circle_in: read (%f, %f, %f)\n", result->center.x,
+       sprintf(buf2, "widget_in: read (%f, %f, %f)\n", result->center.x,
        result->center.y,result->radius);
        return(result);
 }
 
 char *
-circle_out(circle)
-    CIRCLE     *circle;
+widget_out(widget)
+    WIDGET     *widget;
 {
     char       *result;
 
-    if (circle == NULL)
+    if (widget == NULL)
        return(NULL);
 
     result = (char *) palloc(60);
     (void) sprintf(result, "(%g,%g,%g)",
-                  circle->center.x, circle->center.y, circle->radius);
+                  widget->center.x, widget->center.y, widget->radius);
     return(result);
 }
 
 int
-pt_in_circle(point, circle)
+pt_in_widget(point, widget)
        Point   *point;
-       CIRCLE  *circle;
+       WIDGET  *widget;
 {
        extern double   point_dt();
 
-       return( point_dt(point, &circle->center) < circle->radius );
+       return( point_dt(point, &widget->center) < widget->radius );
 }
 
 #define ABS(X) ((X) > 0 ? (X) : -(X))
@@ -247,8 +249,8 @@ BOX *box;
 {
        int width, height;
 
-       width  = ABS(box->xh - box->xl);
-       height = ABS(box->yh - box->yl);
+       width  = ABS(box->high.x - box->low.x);
+       height = ABS(box->high.y - box->low.y);
        return (width * height);
 }
 
index 60e44207820c652479d3dbac7c571b63f6994a07..74fdd8eb4f90568c5338a8178783abe9be21056e 100644 (file)
@@ -10,8 +10,8 @@ CREATE OPERATOR ## (
 
 CREATE OPERATOR <% (
    leftarg = point,
-   rightarg = circle,
-   procedure = pt_in_circle,
+   rightarg = widget,
+   procedure = pt_in_widget,
    commutator = >=% 
 );
 
index 87d1737c64079119dabab46660aa7dfae6fa390e..1a75ba52950623dda992d598329034ab72cfbe1f 100644 (file)
@@ -3,10 +3,10 @@
 --
 --
 
-CREATE TYPE circle (
+CREATE TYPE widget (
    internallength = 24, 
-   input = circle_in,
-   output = circle_out,
+   input = widget_in,
+   output = widget_out,
    alignment = double
 );