1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
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
|
/*
* $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 */
#include <stdio.h>
#include <string.h> /* for memset() */
#include <postgres.h>
#include "utils/geo_decls.h" /* includes <math.h> */
#include "executor/executor.h" /* For GetAttributeByName */
#define P_MAXDIG 12
#define LDELIM '('
#define RDELIM ')'
#define DELIM ','
typedef void *TUPLE;
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 buf[2*(P_MAXDIG)+20];
sprintf(output, "(1, %*d", P_MAXDIG, poly->npts);
for (i=0; i<poly->npts; i++)
{
sprintf(buf, ",%*g,%*g", P_MAXDIG, poly->p[i].x, P_MAXDIG, poly->p[i].y);
strcat(output, buf);
}
sprintf(buf, "%c", RDELIM);
strcat(output, buf);
return(path_in(output));
}
/* 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;
bool found; /* We've found the intersection */
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++)
{
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;
}
ln = line_construct_pp(&seg2.p[0], &seg2.p[1]);
retval = interpt_sl(&seg1, ln);
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);
}
/* 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;
} WIDGET;
extern WIDGET *widget_in (char *str);
extern char *widget_out (WIDGET *widget);
extern int pt_in_widget (Point *point, WIDGET *widget);
#define NARGS 3
WIDGET *
widget_in(str)
char *str;
{
char *p, *coord[NARGS], buf2[1000];
int i;
WIDGET *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 = (WIDGET *) palloc(sizeof(WIDGET));
result->center.x = atof(coord[0]);
result->center.y = atof(coord[1]);
result->radius = atof(coord[2]);
sprintf(buf2, "widget_in: read (%f, %f, %f)\n", result->center.x,
result->center.y,result->radius);
return(result);
}
char *
widget_out(widget)
WIDGET *widget;
{
char *result;
if (widget == NULL)
return(NULL);
result = (char *) palloc(60);
(void) sprintf(result, "(%g,%g,%g)",
widget->center.x, widget->center.y, widget->radius);
return(result);
}
int
pt_in_widget(point, widget)
Point *point;
WIDGET *widget;
{
extern double point_dt();
return( point_dt(point, &widget->center) < widget->radius );
}
#define ABS(X) ((X) > 0 ? (X) : -(X))
int
boxarea(box)
BOX *box;
{
int width, height;
width = ABS(box->high.x - box->low.x);
height = ABS(box->high.y - box->low.y);
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);
}
|