272 lines
5.6 KiB
C
272 lines
5.6 KiB
C
|
/*
|
||
|
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.1.1.1 1996/07/09 06:22:24 scrappy Exp $
|
||
|
*/
|
||
|
|
||
|
#include <float.h> /* faked on sunos */
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include "utils/geo-decls.h" /* includes <math.h> */
|
||
|
#include "libpq-fe.h"
|
||
|
|
||
|
#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;
|
||
|
|
||
|
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 (lseg_intersect(&seg1, &seg2))
|
||
|
{
|
||
|
ln = line_construct_pp(&seg2.p[0], &seg2.p[1]);
|
||
|
retval = interpt_sl(&seg1, ln);
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
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);
|
||
|
}
|