regress.c 5.9 KB
Newer Older
1
/*
2
 * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.6 1997/04/22 17:33:00 scrappy Exp $
3 4 5 6
 */

#include <float.h>		/* faked on sunos */
#include <stdio.h>
B
Bryan Henderson 已提交
7
#include <string.h>   /* for memset() */
8

M
Marc G. Fournier 已提交
9 10
#include <postgres.h>

11
#include "utils/geo_decls.h"	/* includes <math.h> */
B
Bryan Henderson 已提交
12
#include "executor/executor.h"  /* For GetAttributeByName */
13 14 15 16 17 18

#define P_MAXDIG 12
#define LDELIM		'('
#define RDELIM		')'
#define	DELIM		','

19 20
typedef void *TUPLE;

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
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);
106
    char buf[2*(P_MAXDIG)+20];
107

108
    sprintf(output, "(1, %*d", P_MAXDIG, poly->npts);
109

110
    for (i=0; i<poly->npts; i++)
111
     {
112 113
	 sprintf(buf, ",%*g,%*g", P_MAXDIG, poly->p[i].x, P_MAXDIG, poly->p[i].y);
	 strcat(output, buf);
114 115
     }

116 117 118
    sprintf(buf, "%c", RDELIM);
    strcat(output, buf);
    return(path_in(output));
119 120 121 122 123 124 125 126 127 128 129 130 131
}

/* 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;
B
Bryan Henderson 已提交
132
    bool found;  /* We've found the intersection */
133

B
Bryan Henderson 已提交
134 135 136 137
    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++)
138
       {
B
Bryan Henderson 已提交
139 140 141
           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;
142 143
       }

B
Bryan Henderson 已提交
144 145 146
    ln = line_construct_pp(&seg2.p[0], &seg2.p[1]);
    retval = interpt_sl(&seg1, ln);
    
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
    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);
}

176 177 178 179 180
/* 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
 */

181 182 183
typedef struct {
	Point	center;
	double	radius;
184
} WIDGET;
185

186 187 188
extern WIDGET *widget_in (char *str);
extern char *widget_out (WIDGET *widget);
extern int pt_in_widget (Point *point, WIDGET *widget);
189 190 191

#define NARGS	3

192 193
WIDGET *
widget_in(str)
194 195 196 197
char	*str;
{
	char	*p, *coord[NARGS], buf2[1000];
	int	i;
198
	WIDGET	*result;
199 200 201 202 203 204 205 206

	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);
207
	result = (WIDGET *) palloc(sizeof(WIDGET));
208 209 210 211
	result->center.x = atof(coord[0]);
	result->center.y = atof(coord[1]);
	result->radius = atof(coord[2]);

212
	sprintf(buf2, "widget_in: read (%f, %f, %f)\n", result->center.x,
213 214 215 216 217
	result->center.y,result->radius);
	return(result);
}

char *
218 219
widget_out(widget)
    WIDGET	*widget;
220 221 222
{
    char	*result;

223
    if (widget == NULL)
224 225 226 227
	return(NULL);

    result = (char *) palloc(60);
    (void) sprintf(result, "(%g,%g,%g)",
228
		   widget->center.x, widget->center.y, widget->radius);
229 230 231 232
    return(result);
}

int
233
pt_in_widget(point, widget)
234
	Point	*point;
235
	WIDGET	*widget;
236 237 238
{
	extern double	point_dt();

239
	return( point_dt(point, &widget->center) < widget->radius );
240 241 242 243 244 245 246 247 248 249 250 251
}

#define ABS(X) ((X) > 0 ? (X) : -(X))

int
boxarea(box)

BOX *box;

{
	int width, height;

252 253
	width  = ABS(box->high.x - box->low.x);
	height = ABS(box->high.y - box->low.y);
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
	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);
}