1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1996-11-12 12:09:13 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.3 1996/11/12 11:09:13 bryanh Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <float.h> /* faked on sunos */
|
|
|
|
#include <stdio.h>
|
1996-11-12 12:09:13 +01:00
|
|
|
#include <string.h> /* for memset() */
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-11 17:33:12 +01:00
|
|
|
#include <postgres.h>
|
1996-11-12 12:09:13 +01:00
|
|
|
#include "libpq-fe.h"
|
1996-11-11 17:33:12 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "utils/geo-decls.h" /* includes <math.h> */
|
1996-11-12 12:09:13 +01:00
|
|
|
#include "executor/executor.h" /* For GetAttributeByName */
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
#define P_MAXDIG 12
|
|
|
|
#define LDELIM '('
|
|
|
|
#define RDELIM ')'
|
|
|
|
#define DELIM ','
|
|
|
|
|
|
|
|
extern double *regress_dist_ptpath (Point *pt, PATH *path);
|
|
|
|
extern double *regress_path_dist (PATH *p1, PATH *p2);
|
|
|
|
extern PATH *poly2path (POLYGON *poly);
|
|
|
|
extern Point *interpt_pp (PATH *p1, PATH *p2);
|
|
|
|
extern void regress_lseg_construct (LSEG *lseg, Point *pt1, Point *pt2);
|
|
|
|
extern char overpaid (TUPLE tuple);
|
|
|
|
extern int boxarea (BOX *box);
|
|
|
|
extern char *reverse_c16 (char *string);
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Distance from a point to a path
|
|
|
|
*/
|
|
|
|
double *
|
|
|
|
regress_dist_ptpath(pt, path)
|
|
|
|
Point *pt;
|
|
|
|
PATH *path;
|
|
|
|
{
|
|
|
|
double *result;
|
|
|
|
double *tmp;
|
|
|
|
int i;
|
|
|
|
LSEG lseg;
|
|
|
|
|
|
|
|
switch (path->npts) {
|
|
|
|
case 0:
|
|
|
|
result = PALLOCTYPE(double);
|
|
|
|
*result = Abs((double) DBL_MAX); /* +infinity */
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
result = point_distance(pt, &path->p[0]);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* 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) {
|
|
|
|
regress_lseg_construct(&lseg, &path->p[i], &path->p[i+1]);
|
|
|
|
tmp = dist_ps(pt, &lseg);
|
|
|
|
if (i == 0 || *tmp < *result)
|
|
|
|
*result = *tmp;
|
|
|
|
PFREE(tmp);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this essentially does a cartesian product of the lsegs in the
|
|
|
|
two paths, and finds the min distance between any two lsegs */
|
|
|
|
double *
|
|
|
|
regress_path_dist(p1, p2)
|
|
|
|
PATH *p1;
|
|
|
|
PATH *p2;
|
|
|
|
{
|
|
|
|
double *min, *tmp;
|
|
|
|
int i,j;
|
|
|
|
LSEG seg1, seg2;
|
|
|
|
|
|
|
|
regress_lseg_construct(&seg1, &p1->p[0], &p1->p[1]);
|
|
|
|
regress_lseg_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++)
|
|
|
|
{
|
|
|
|
regress_lseg_construct(&seg1, &p1->p[i], &p1->p[i+1]);
|
|
|
|
regress_lseg_construct(&seg2, &p2->p[j], &p2->p[j+1]);
|
|
|
|
|
|
|
|
if (*min < *(tmp = lseg_distance(&seg1, &seg2)))
|
|
|
|
*min = *tmp;
|
|
|
|
PFREE(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(min);
|
|
|
|
}
|
|
|
|
|
|
|
|
PATH *
|
|
|
|
poly2path(poly)
|
|
|
|
POLYGON *poly;
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *output = (char *)PALLOC(2*(P_MAXDIG + 1)*poly->npts + 64);
|
|
|
|
char *outptr = output;
|
|
|
|
double *xp, *yp;
|
|
|
|
|
|
|
|
sprintf(outptr, "(1, %*d", P_MAXDIG, poly->npts);
|
|
|
|
xp = (double *) poly->pts;
|
|
|
|
yp = (double *) (poly->pts + (poly->npts * sizeof(double *)));
|
|
|
|
|
|
|
|
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(path_in(outptr));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return the point where two paths intersect. Assumes that they do. */
|
|
|
|
Point *
|
|
|
|
interpt_pp(p1,p2)
|
|
|
|
PATH *p1;
|
|
|
|
PATH *p2;
|
|
|
|
{
|
|
|
|
|
|
|
|
Point *retval;
|
|
|
|
int i,j;
|
|
|
|
LSEG seg1, seg2;
|
|
|
|
LINE *ln;
|
1996-11-12 12:09:13 +01:00
|
|
|
bool found; /* We've found the intersection */
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-12 12:09:13 +01:00
|
|
|
found = false; /* Haven't found it yet */
|
|
|
|
|
|
|
|
for (i = 0; i < p1->npts - 1 && !found; i++)
|
|
|
|
for (j = 0; j < p2->npts - 1 && !found; j++)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1996-11-12 12:09:13 +01:00
|
|
|
regress_lseg_construct(&seg1, &p1->p[i], &p1->p[i+1]);
|
|
|
|
regress_lseg_construct(&seg2, &p2->p[j], &p2->p[j+1]);
|
|
|
|
if (lseg_intersect(&seg1, &seg2)) found = true;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1996-11-12 12:09:13 +01:00
|
|
|
ln = line_construct_pp(&seg2.p[0], &seg2.p[1]);
|
|
|
|
retval = interpt_sl(&seg1, ln);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
return(retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* like lseg_construct, but assume space already allocated */
|
|
|
|
void
|
|
|
|
regress_lseg_construct(lseg, pt1, pt2)
|
|
|
|
LSEG *lseg;
|
|
|
|
Point *pt1;
|
|
|
|
Point *pt2;
|
|
|
|
{
|
|
|
|
lseg->p[0].x = pt1->x;
|
|
|
|
lseg->p[0].y = pt1->y;
|
|
|
|
lseg->p[1].x = pt2->x;
|
|
|
|
lseg->p[1].y = pt2->y;
|
|
|
|
lseg->m = point_sl(pt1, pt2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char overpaid(tuple)
|
|
|
|
TUPLE tuple;
|
|
|
|
{
|
|
|
|
bool isnull;
|
|
|
|
long salary;
|
|
|
|
|
|
|
|
salary = (long)GetAttributeByName(tuple, "salary", &isnull);
|
|
|
|
return(salary > 699);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
Point center;
|
|
|
|
double radius;
|
|
|
|
} CIRCLE;
|
|
|
|
|
|
|
|
extern CIRCLE *circle_in (char *str);
|
|
|
|
extern char *circle_out (CIRCLE *circle);
|
|
|
|
extern int pt_in_circle (Point *point, CIRCLE *circle);
|
|
|
|
|
|
|
|
#define NARGS 3
|
|
|
|
|
|
|
|
CIRCLE *
|
|
|
|
circle_in(str)
|
|
|
|
char *str;
|
|
|
|
{
|
|
|
|
char *p, *coord[NARGS], buf2[1000];
|
|
|
|
int i;
|
|
|
|
CIRCLE *result;
|
|
|
|
|
|
|
|
if (str == NULL)
|
|
|
|
return(NULL);
|
|
|
|
for (i = 0, p = str; *p && i < NARGS && *p != RDELIM; p++)
|
|
|
|
if (*p == ',' || (*p == LDELIM && !i))
|
|
|
|
coord[i++] = p + 1;
|
|
|
|
if (i < NARGS - 1)
|
|
|
|
return(NULL);
|
|
|
|
result = (CIRCLE *) palloc(sizeof(CIRCLE));
|
|
|
|
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,
|
|
|
|
result->center.y,result->radius);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
circle_out(circle)
|
|
|
|
CIRCLE *circle;
|
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
if (circle == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
result = (char *) palloc(60);
|
|
|
|
(void) sprintf(result, "(%g,%g,%g)",
|
|
|
|
circle->center.x, circle->center.y, circle->radius);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
pt_in_circle(point, circle)
|
|
|
|
Point *point;
|
|
|
|
CIRCLE *circle;
|
|
|
|
{
|
|
|
|
extern double point_dt();
|
|
|
|
|
|
|
|
return( point_dt(point, &circle->center) < circle->radius );
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ABS(X) ((X) > 0 ? (X) : -(X))
|
|
|
|
|
|
|
|
int
|
|
|
|
boxarea(box)
|
|
|
|
|
|
|
|
BOX *box;
|
|
|
|
|
|
|
|
{
|
|
|
|
int width, height;
|
|
|
|
|
|
|
|
width = ABS(box->xh - box->xl);
|
|
|
|
height = ABS(box->yh - box->yl);
|
|
|
|
return (width * height);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
reverse_c16(string)
|
|
|
|
char *string;
|
|
|
|
{
|
|
|
|
register i;
|
|
|
|
int len;
|
|
|
|
char *new_string;
|
|
|
|
|
|
|
|
if (!(new_string = palloc(16))) {
|
|
|
|
fprintf(stderr, "reverse_c16: palloc failed\n");
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
memset(new_string, 0, 16);
|
|
|
|
for (i = 0; i < 16 && string[i]; ++i)
|
|
|
|
;
|
|
|
|
if (i == 16 || !string[i])
|
|
|
|
--i;
|
|
|
|
len = i;
|
|
|
|
for (; i >= 0; --i)
|
|
|
|
new_string[len-i] = string[i];
|
|
|
|
return(new_string);
|
|
|
|
}
|