~ubuntu-branches/ubuntu/jaunty/grace/jaunty

« back to all changes in this revision

Viewing changes to src/regionutils.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2002-03-19 14:19:58 UTC
  • Revision ID: james.westby@ubuntu.com-20020319141958-5gxna6vo1ek3zjml
Tags: upstream-5.1.7
ImportĀ upstreamĀ versionĀ 5.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Grace - Graphics for Exploratory Data Analysis
 
3
 * 
 
4
 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
 
5
 * 
 
6
 * Copyright (c) 1991-1995 Paul J Turner, Portland, OR
 
7
 * Copyright (c) 1996-2001 Grace Development Team
 
8
 * 
 
9
 * Maintained by Evgeny Stambulchik <fnevgeny@plasma-gate.weizmann.ac.il>
 
10
 * 
 
11
 * 
 
12
 *                           All Rights Reserved
 
13
 * 
 
14
 *    This program is free software; you can redistribute it and/or modify
 
15
 *    it under the terms of the GNU General Public License as published by
 
16
 *    the Free Software Foundation; either version 2 of the License, or
 
17
 *    (at your option) any later version.
 
18
 * 
 
19
 *    This program is distributed in the hope that it will be useful,
 
20
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 *    GNU General Public License for more details.
 
23
 * 
 
24
 *    You should have received a copy of the GNU General Public License
 
25
 *    along with this program; if not, write to the Free Software
 
26
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
27
 */
 
28
 
 
29
/*
 
30
 *
 
31
 * routines to allocate, manipulate, and return
 
32
 * information about regions.
 
33
 *
 
34
 */
 
35
 
 
36
#include <config.h>
 
37
 
 
38
#include <stdio.h>
 
39
#include <stdlib.h>
 
40
 
 
41
#include "globals.h"
 
42
 
 
43
#include "draw.h"
 
44
#include "graphs.h"
 
45
#include "utils.h"
 
46
#include "protos.h"
 
47
 
 
48
int regiontype = 0;
 
49
 
 
50
/*
 
51
 * see if (x,y) lies inside the plot
 
52
 */
 
53
int inbounds(int gno, double x, double y)
 
54
{
 
55
    WPoint wp;
 
56
    
 
57
    wp.x = x;
 
58
    wp.y = y;
 
59
    return is_validWPoint(wp);
 
60
}
 
61
 
 
62
int isactive_region(int regno)
 
63
{
 
64
    return (regno == MAXREGION || regno == MAXREGION + 1 || rg[regno].active == TRUE);
 
65
}
 
66
 
 
67
char *region_types(int it, int which)
 
68
{
 
69
    char *s;
 
70
 
 
71
    s = "UNDEFINED";
 
72
    switch (it) {
 
73
    case REGION_TOLEFT:
 
74
        s = "REGION_TOLEFT";
 
75
        break;
 
76
    case REGION_TORIGHT:
 
77
        s = "REGION_TORIGHT";
 
78
        break;
 
79
    case REGION_ABOVE:
 
80
        s = "REGION_ABOVE";
 
81
        break;
 
82
    case REGION_BELOW:
 
83
        s = "REGION_BELOW";
 
84
        break;
 
85
    case REGION_POLYI:
 
86
        if (which) {
 
87
            s = "REGION_POLYI";
 
88
        } else {
 
89
            s = "INSIDE POLY";
 
90
        }
 
91
        break;
 
92
    case REGION_POLYO:
 
93
        if (which) {
 
94
            s = "REGION_POLYO";
 
95
        } else {
 
96
            s = "OUTSIDE POLY";
 
97
        }
 
98
        break;
 
99
    case REGION_HORIZI:
 
100
      s ="REGION_HORIZI";
 
101
      break;
 
102
    case REGION_VERTI:
 
103
      s ="REGION_VERTI";
 
104
      break;
 
105
    case REGION_HORIZO:
 
106
       s ="REGION_HORIZO";
 
107
      break;
 
108
    case REGION_VERTO:
 
109
      s ="REGION_VERTO";
 
110
      break;
 
111
 
 
112
    }
 
113
    return s;
 
114
}
 
115
 
 
116
void kill_region(int r)
 
117
{
 
118
    if (rg[r].active) {
 
119
        XCFREE(rg[r].x);
 
120
        XCFREE(rg[r].y);
 
121
        rg[r].active = FALSE;
 
122
        rg[r].n = 0;
 
123
        set_dirtystate();
 
124
    }
 
125
}
 
126
 
 
127
void kill_all_regions(void)
 
128
{
 
129
    int r;
 
130
    for (r = 0; r < MAXREGION; r++) {
 
131
        kill_region(r);
 
132
    }
 
133
}
 
134
 
 
135
void activate_region(int r, int type, int linkto)
 
136
{
 
137
    kill_region(r);
 
138
    rg[r].active = TRUE;
 
139
    rg[r].type = type;
 
140
    rg[r].linkto = linkto;
 
141
    set_dirtystate();
 
142
}
 
143
 
 
144
 
 
145
/*
 
146
 * report on sets in a region
 
147
 */
 
148
void reporton_region(int gno, int rno, int type)
 
149
{
 
150
    char buf[256];
 
151
    int i, j, first, contained;
 
152
    double *x, *y;
 
153
    sprintf(buf, "\nRegion R%1d contains:\n", rno);
 
154
    stufftext(buf);
 
155
    for (j = 0; j < number_of_sets(gno); j++) {
 
156
        if (is_set_active(gno, j)) {
 
157
            x = getx(gno, j);
 
158
            y = gety(gno, j);
 
159
            first = 1;
 
160
            contained = 0;
 
161
            for (i = 0; i < getsetlength(gno, j); i++) {
 
162
                if (inregion(rno, x[i], y[i])) {
 
163
                    contained = 1;
 
164
                    switch (type) {
 
165
                    case 0:     /* report on sets */
 
166
                        if (first) {
 
167
                            first = 0;
 
168
                            sprintf(buf, "  Set S%1d\n", j);
 
169
                            stufftext(buf);
 
170
                        }
 
171
                        break;
 
172
                    case 1:     /* points */
 
173
                        if (first) {
 
174
                            first = 0;
 
175
                            sprintf(buf, "  Set S%1d\n", j);
 
176
                            stufftext(buf);
 
177
                        }
 
178
                        sprintf(buf, "    %d %f %f\n", i + 1, x[i], y[i]);
 
179
                        stufftext(buf);
 
180
                        break;
 
181
                    }
 
182
                } else {
 
183
                    contained = 0;
 
184
                }
 
185
            }
 
186
        }
 
187
    }
 
188
    stufftext("\n");
 
189
}
 
190
 
 
191
void load_poly_region(int r, int gno, int n, WPoint *wps)
 
192
{
 
193
    int i;
 
194
 
 
195
    if (n > 2) {
 
196
        activate_region(r, regiontype, gno);
 
197
        rg[r].n = n;
 
198
        rg[r].x = xcalloc(n, SIZEOF_DOUBLE);
 
199
        rg[r].y = xcalloc(n, SIZEOF_DOUBLE);
 
200
        for (i = 0; i < n; i++) {
 
201
            rg[r].x[i] = wps[i].x;
 
202
            rg[r].y[i] = wps[i].y;
 
203
        }
 
204
    }
 
205
}
 
206
 
 
207
/*
 
208
 * routines to determine if a point lies in a polygon
 
209
*/
 
210
int intersect_to_left(double x, double y, double x1, double y1, double x2, double y2)
 
211
{
 
212
    double xtmp, m, b;
 
213
 
 
214
    /* ignore horizontal lines */
 
215
    if (y1 == y2) {
 
216
        return 0;
 
217
    }
 
218
    /* not contained vertically */
 
219
    if (((y < y1) && (y < y2)) || ((y > y1) && (y > y2))) {
 
220
        return 0;
 
221
    }
 
222
    /* none of the above, compute the intersection */
 
223
    if ((xtmp = x2 - x1) != 0.0) {
 
224
        m = (y2 - y1) / xtmp;
 
225
        b = y1 - m * x1;
 
226
        xtmp = (y - b) / m;
 
227
    } else {
 
228
        xtmp = x1;
 
229
    }
 
230
    if (xtmp <= x) {
 
231
        /* check for intersections at a vertex */
 
232
        /* if this is the max ordinate then accept */
 
233
        if (y == y1) {
 
234
            if (y1 > y2) {
 
235
                return 1;
 
236
            } else {
 
237
                return 0;
 
238
            }
 
239
        }
 
240
        /* check for intersections at a vertex */
 
241
        if (y == y2) {
 
242
            if (y2 > y1) {
 
243
                return 1;
 
244
            } else {
 
245
                return 0;
 
246
            }
 
247
        }
 
248
        /* no vertices intersected */
 
249
        return 1;
 
250
    }
 
251
    return 0;
 
252
}
 
253
 
 
254
/*
 
255
 * determine if (x,y) is in the polygon xlist[], ylist[]
 
256
 */
 
257
int inbound(double x, double y, double *xlist, double *ylist, int n)
 
258
{
 
259
    int i, l = 0;
 
260
 
 
261
    for (i = 0; i < n; i++) {
 
262
        l += intersect_to_left(x, y, xlist[i], ylist[i], xlist[(i + 1) % n], ylist[(i + 1) % n]);
 
263
    }
 
264
    return l % 2;
 
265
}
 
266
 
 
267
/*
 
268
 * routines to determine if a point lies to the left of an infinite line
 
269
*/
 
270
int isleft(double x, double y, double x1, double y1, double x2, double y2)
 
271
{
 
272
    double xtmp, m, b;
 
273
 
 
274
    /* horizontal lines */
 
275
    if (y1 == y2) {
 
276
        return 0;
 
277
    }
 
278
    /* none of the above, compute the intersection */
 
279
    if ((xtmp = x2 - x1) != 0.0) {
 
280
        m = (y2 - y1) / xtmp;
 
281
        b = y1 - m * x1;
 
282
        xtmp = (y - b) / m;
 
283
    } else {
 
284
        xtmp = x1;
 
285
    }
 
286
    if (xtmp >= x) {
 
287
        return 1;
 
288
    }
 
289
    return 0;
 
290
}
 
291
 
 
292
 
 
293
/*
 
294
 * routines to determine if a point lies to the left of an infinite line
 
295
*/
 
296
int isright(double x, double y, double x1, double y1, double x2, double y2)
 
297
{
 
298
    double xtmp, m, b;
 
299
 
 
300
    /* horizontal lines */
 
301
    if (y1 == y2) {
 
302
        return 0;
 
303
    }
 
304
    if ((xtmp = x2 - x1) != 0.0) {
 
305
        m = (y2 - y1) / xtmp;
 
306
        b = y1 - m * x1;
 
307
        xtmp = (y - b) / m;
 
308
    } else {
 
309
        xtmp = x1;
 
310
    }
 
311
    if (xtmp <= x) {
 
312
        return 1;
 
313
    }
 
314
    return 0;
 
315
}
 
316
 
 
317
/*
 
318
 * routines to determine if a point lies above an infinite line
 
319
*/
 
320
int isabove(double x, double y, double x1, double y1, double x2, double y2)
 
321
{
 
322
    double ytmp, m, b;
 
323
 
 
324
    /* vertical lines */
 
325
    if (x1 == x2) {
 
326
        return 0;
 
327
    }
 
328
    if ((ytmp = y2 - y1) != 0.0) {
 
329
        m = ytmp / (x2 - x1);
 
330
        b = y1 - m * x1;
 
331
        ytmp = m * x + b;
 
332
    } else {
 
333
        ytmp = y1;
 
334
    }
 
335
    if (ytmp <= y) {
 
336
        return 1;
 
337
    }
 
338
    return 0;
 
339
}
 
340
 
 
341
/*
 
342
 * routines to determine if a point lies below an infinite line
 
343
*/
 
344
int isbelow(double x, double y, double x1, double y1, double x2, double y2)
 
345
{
 
346
    double ytmp, m, b;
 
347
 
 
348
    /* vertical lines */
 
349
    if (x1 == x2) {
 
350
        return 0;
 
351
    }
 
352
    if ((ytmp = y2 - y1) != 0.0) {
 
353
        m = ytmp / (x2 - x1);
 
354
        b = y1 - m * x1;
 
355
        ytmp = m * x + b;
 
356
    } else {
 
357
        ytmp = y1;
 
358
    }
 
359
    if (ytmp >= y) {
 
360
        return 1;
 
361
    }
 
362
    return 0;
 
363
}
 
364
 
 
365
int inregion(int regno, double x, double y)
 
366
{
 
367
    if (regno == MAXREGION) {
 
368
        return (inbounds(get_cg() , x, y));
 
369
    }
 
370
    if (regno == MAXREGION + 1) {
 
371
        return (!inbounds(get_cg() , x, y));
 
372
    }
 
373
    if (rg[regno].active == TRUE) {
 
374
        switch (rg[regno].type) {
 
375
        case REGION_POLYI:
 
376
            if (inbound(x, y, rg[regno].x, rg[regno].y, rg[regno].n)) {
 
377
                return 1;
 
378
            }
 
379
            break;
 
380
        case REGION_POLYO:
 
381
            if (!inbound(x, y, rg[regno].x, rg[regno].y, rg[regno].n)) {
 
382
                return 1;
 
383
            }
 
384
            break;
 
385
        case REGION_TORIGHT:
 
386
            if (isright(x, y, rg[regno].x1, rg[regno].y1, rg[regno].x2, rg[regno].y2)) {
 
387
                return 1;
 
388
            }
 
389
            break;
 
390
        case REGION_TOLEFT:
 
391
            if (isleft(x, y, rg[regno].x1, rg[regno].y1, rg[regno].x2, rg[regno].y2)) {
 
392
                return 1;
 
393
            }
 
394
            break;
 
395
        case REGION_ABOVE:
 
396
            if (isabove(x, y, rg[regno].x1, rg[regno].y1, rg[regno].x2, rg[regno].y2)) {
 
397
                return 1;
 
398
            }
 
399
            break;
 
400
        case REGION_BELOW:
 
401
            if (isbelow(x, y, rg[regno].x1, rg[regno].y1, rg[regno].x2, rg[regno].y2)) {
 
402
                return 1;
 
403
            }
 
404
            break;
 
405
        case REGION_HORIZI:
 
406
          return (x >= rg[regno].x1) && ( x <= rg[regno].x2);
 
407
          break;
 
408
        case REGION_VERTI:
 
409
          return (y >= rg[regno].y1) && ( y <= rg[regno].y2);
 
410
          break;
 
411
        case REGION_HORIZO:
 
412
          return !( (x >= rg[regno].x1) && ( x <= rg[regno].x2) );
 
413
          break;
 
414
        case REGION_VERTO:
 
415
          return !( (y >= rg[regno].y1) && ( y <= rg[regno].y2) );
 
416
          break;
 
417
 
 
418
        }
 
419
    }
 
420
    return 0;
 
421
}