~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to display/d.rast.arrow/main.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 ****************************************************************************
 
3
 *
 
4
 * MODULE:       d.rast.arrow
 
5
 * AUTHOR(S):    Chris Rewerts, Agricultural Engineering, Purdue University
 
6
 * PURPOSE:      Draw arrows on slope/aspect maps. 
 
7
 * COPYRIGHT:    (C) 2000, 2010 by the GRASS Development Team
 
8
 *
 
9
 *              This program is free software under the GNU General Public
 
10
 *              License (>=v2). Read the file COPYING that comes with GRASS
 
11
 *              for details.
 
12
 *
 
13
 *****************************************************************************/
 
14
 
 
15
/* some minor cleanup done by Andreas Lange, andreas.lange@rhein-main.de
 
16
 * Update to handle NULLs and floating point aspect maps: Hamish Bowman, Aug 2004
 
17
 * Update for 360 degree arrows and magnitude scaling:  Hamish Bowman, Oct 2005
 
18
 */
 
19
 
 
20
/*
 
21
 *   Chris Rewerts, Agricultural Engineering, Purdue University
 
22
 *   rewerts@ecn.purdue.edu  March 1991
 
23
 *
 
24
 *   d.rast.arrow
 
25
 *
 
26
 *   Usage:  d.rast.arrow
 
27
 * 
 
28
 *   This program used Dgrid's sources as a beginning. Purpose of Darrow
 
29
 *   is to read an aspect layer produced by slope.aspect or by the 
 
30
 *   programs created for the ANSWERS or AGNPS Hydrology Toolbox
 
31
 *   endeavors.  d.rast.arrow draws an arrow on the graphic display
 
32
 *   of each cell, so that the flow pattern computed as an aspect
 
33
 *   layer can be easily seen. Other symbols ("?", "X") may be drawn
 
34
 *   as needed.
 
35
 */
 
36
 
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
39
#include <math.h>
 
40
#include <grass/gis.h>
 
41
#include <grass/raster.h>
 
42
#include <grass/display.h>
 
43
#include <grass/colors.h>
 
44
#include <grass/glocale.h>
 
45
 
 
46
# define RpD ((2 * M_PI) / 360.)        /* radians/degree */
 
47
# define D2R(d) (double)(d * RpD)       /* degrees->radians */
 
48
 
 
49
static void arrow_mag(double, double);
 
50
static void arrow_360(double);
 
51
static void arrow_se(void);
 
52
static void arrow_ne(void);
 
53
static void arrow_nw(void);
 
54
static void arrow_sw(void);
 
55
static void arrow_e(void);
 
56
static void arrow_w(void);
 
57
static void arrow_s(void);
 
58
static void arrow_n(void);
 
59
static void draw_x(void);
 
60
static void unknown_(void);
 
61
 
 
62
static char *layer_name;
 
63
static int map_type, arrow_color, grid_color, x_color, unknown_color;
 
64
static int row, col;
 
65
 
 
66
int main(int argc, char **argv)
 
67
{
 
68
    struct Cell_head window;
 
69
    RASTER_MAP_TYPE raster_type, mag_raster_type = -1;
 
70
    int layer_fd;
 
71
    void *raster_row, *ptr;
 
72
    int nrows, ncols;
 
73
    int aspect_c = -1;
 
74
    float aspect_f = -1.0;
 
75
 
 
76
    double scale;
 
77
    int skip, no_arrow;
 
78
    char *mag_map = NULL;
 
79
    void *mag_raster_row = NULL, *mag_ptr = NULL;
 
80
    double length = -1;
 
81
    int mag_fd = -1;
 
82
    struct FPRange range;
 
83
    double mag_min, mag_max;
 
84
 
 
85
    struct GModule *module;
 
86
    struct Option *opt1, *opt2, *opt3, *opt4, *opt5,
 
87
        *opt6, *opt7, *opt8, *opt9;
 
88
    struct Flag *align;
 
89
 
 
90
    double t, b, l, r;
 
91
 
 
92
    G_gisinit(argv[0]);
 
93
 
 
94
    module = G_define_module();
 
95
    G_add_keyword(_("display"));
 
96
    G_add_keyword(_("map annotations"));
 
97
    G_add_keyword(_("raster"));
 
98
    module->description =
 
99
        _("Draws arrows representing cell aspect direction "
 
100
          "for a raster map containing aspect data.");
 
101
 
 
102
    opt1 = G_define_standard_option(G_OPT_R_MAP);
 
103
    opt1->description = _("Name of raster aspect map to be displayed");
 
104
 
 
105
    opt2 = G_define_option();
 
106
    opt2->key = "type";
 
107
    opt2->type = TYPE_STRING;
 
108
    opt2->required = NO;
 
109
    opt2->answer = "grass";
 
110
    opt2->options = "grass,compass,agnps,answers";
 
111
    opt2->description = _("Type of existing raster aspect map");
 
112
 
 
113
    opt3 = G_define_standard_option(G_OPT_C);
 
114
    opt3->key = "color";
 
115
    opt3->answer = "green";
 
116
    opt3->label = _("Color for drawing arrows");
 
117
    opt3->guisection = _("Colors");
 
118
    
 
119
    opt4 = G_define_standard_option(G_OPT_CN);
 
120
    opt4->key = "grid_color";
 
121
    opt4->answer = "gray";
 
122
    opt4->label = _("Color for drawing drawing grid");
 
123
    opt4->guisection = _("Colors");
 
124
 
 
125
    opt5 = G_define_standard_option(G_OPT_CN);
 
126
    opt5->key = "null_color";
 
127
    opt5->answer = DEFAULT_FG_COLOR;
 
128
    opt5->label = _("Color for drawing null values (X symbol)");
 
129
    opt5->guisection = _("Colors");
 
130
 
 
131
    opt6 = G_define_standard_option(G_OPT_CN);
 
132
    opt6->key = "unknown_color";
 
133
    opt6->answer = "red";
 
134
    opt6->label = _("Color for showing unknown information (? symbol)");
 
135
    opt6->guisection = _("Colors");
 
136
 
 
137
    opt9 = G_define_option();
 
138
    opt9->key = "skip";
 
139
    opt9->type = TYPE_INTEGER;
 
140
    opt9->required = NO;
 
141
    opt9->answer = "1";
 
142
    opt9->description = _("Draw arrow every Nth grid cell");
 
143
 
 
144
    opt7 = G_define_option();
 
145
    opt7->key = "magnitude_map";
 
146
    opt7->type = TYPE_STRING;
 
147
    opt7->required = NO;
 
148
    opt7->multiple = NO;
 
149
    opt7->gisprompt = "old,cell,raster";
 
150
    opt7->description =
 
151
        _("Raster map containing values used for arrow length");
 
152
 
 
153
    opt8 = G_define_option();
 
154
    opt8->key = "scale";
 
155
    opt8->type = TYPE_DOUBLE;
 
156
    opt8->required = NO;
 
157
    opt8->answer = "1.0";
 
158
    opt8->description = _("Scale factor for arrows (magnitude map)");
 
159
 
 
160
    align = G_define_flag();
 
161
    align->key = 'a';
 
162
    align->description = _("Align grids with raster cells");
 
163
 
 
164
 
 
165
    /* Check command line */
 
166
    if (G_parser(argc, argv))
 
167
        exit(EXIT_FAILURE);
 
168
 
 
169
 
 
170
    layer_name = opt1->answer;
 
171
 
 
172
    arrow_color = D_translate_color(opt3->answer);
 
173
 
 
174
    /* Convert none (transparent) to -1 which in this module means
 
175
       that we will not draw things having this color (-1).
 
176
       We don't do that for arrow because we always want them.
 
177
       (This is specified by the gisprompt ('type') of the options.)
 
178
    */
 
179
    if (strcmp("none", opt4->answer) == 0)
 
180
        grid_color = -1;
 
181
    else
 
182
        grid_color = D_translate_color(opt4->answer);
 
183
 
 
184
    if (strcmp("none", opt5->answer) == 0)
 
185
        x_color = -1;
 
186
    else
 
187
        x_color = D_translate_color(opt5->answer);
 
188
 
 
189
    if (strcmp("none", opt6->answer) == 0)
 
190
        unknown_color = -1;
 
191
    else
 
192
        unknown_color = D_translate_color(opt6->answer);
 
193
 
 
194
    if (strcmp("grass", opt2->answer) == 0)
 
195
        map_type = 1;
 
196
    else if (strcmp("agnps", opt2->answer) == 0)
 
197
        map_type = 2;
 
198
    else if (strcmp("answers", opt2->answer) == 0)
 
199
        map_type = 3;
 
200
    else if (strcmp("compass", opt2->answer) == 0)
 
201
        map_type = 4;
 
202
 
 
203
 
 
204
    scale = atof(opt8->answer);
 
205
    if (scale <= 0.0)
 
206
        G_fatal_error(_("Illegal value for scale factor"));
 
207
 
 
208
    skip = atoi(opt9->answer);
 
209
    if (skip <= 0)
 
210
        G_fatal_error(_("Illegal value for skip factor"));
 
211
 
 
212
 
 
213
    if (opt7->answer) {
 
214
        if (map_type != 1 && map_type != 4)
 
215
            G_fatal_error(_("Magnitude is only supported for GRASS and compass aspect maps."));
 
216
 
 
217
        mag_map = opt7->answer;
 
218
    }
 
219
    else if (scale != 1.0)
 
220
        G_warning(_("Scale option requires magnitude_map"));
 
221
 
 
222
 
 
223
    /* Setup driver and check important information */
 
224
    D_open_driver();
 
225
    
 
226
    D_setup(0);
 
227
 
 
228
    /* Read in the map window associated with window */
 
229
    G_get_window(&window);
 
230
 
 
231
    if (align->answer) {
 
232
        struct Cell_head wind;
 
233
 
 
234
        Rast_get_cellhd(layer_name, "", &wind);
 
235
 
 
236
        /* expand window extent by one wind resolution */
 
237
        wind.west += wind.ew_res * ((int)((window.west - wind.west) / wind.ew_res) - (window.west < wind.west));
 
238
        wind.east += wind.ew_res * ((int)((window.east - wind.east) / wind.ew_res) + (window.east > wind.east));
 
239
        wind.south += wind.ns_res * ((int)((window.south - wind.south) / wind.ns_res) - (window.south < wind.south));
 
240
        wind.north += wind.ns_res * ((int)((window.north - wind.north) / wind.ns_res) + (window.north > wind.north));
 
241
 
 
242
        wind.rows = (wind.north - wind.south) / wind.ns_res;
 
243
        wind.cols = (wind.east - wind.west) / wind.ew_res;
 
244
 
 
245
        Rast_set_window(&wind);
 
246
 
 
247
        nrows = wind.rows;
 
248
        ncols = wind.cols;
 
249
 
 
250
        t = (wind.north - window.north) * nrows / (wind.north - wind.south);
 
251
        b = t + (window.north - window.south) * nrows / (wind.north - wind.south);
 
252
        l = (window.west - wind.west) * ncols / (wind.east - wind.west);
 
253
        r = l + (window.east - window.west) * ncols / (wind.east - wind.west);
 
254
    } else {
 
255
        nrows = window.rows;
 
256
        ncols = window.cols;
 
257
 
 
258
        t = 0;
 
259
        b = nrows;
 
260
        l = 0;
 
261
        r = ncols;
 
262
    }
 
263
 
 
264
    D_set_src(t, b, l, r);
 
265
    D_update_conversions();
 
266
 
 
267
    /* figure out arrow scaling if using a magnitude map */
 
268
    if (opt7->answer) {
 
269
        Rast_init_fp_range(&range);     /* really needed? */
 
270
        if (Rast_read_fp_range(mag_map, "", &range) != 1)
 
271
            G_fatal_error(_("Problem reading range file"));
 
272
        Rast_get_fp_range_min_max(&range, &mag_min, &mag_max);
 
273
 
 
274
        scale *= 1.5 / fabs(mag_max);
 
275
        G_debug(3, "scaling=%.2f  rast_max=%.2f", scale, mag_max);
 
276
    }
 
277
 
 
278
    if (grid_color > 0) {       /* ie not "none" */
 
279
        /* Set color */
 
280
        D_use_color(grid_color);
 
281
 
 
282
        /* Draw vertical grids */
 
283
        for (col = 0; col < ncols; col++)
 
284
            D_line_abs(col, 0, col, nrows);
 
285
 
 
286
        /* Draw horizontal grids */
 
287
        for (row = 0; row < nrows; row++)
 
288
            D_line_abs(0, row, ncols, row);
 
289
    }
 
290
 
 
291
    /* open the raster map */
 
292
    layer_fd = Rast_open_old(layer_name, "");
 
293
 
 
294
    raster_type = Rast_get_map_type(layer_fd);
 
295
 
 
296
    /* allocate the cell array */
 
297
    raster_row = Rast_allocate_buf(raster_type);
 
298
 
 
299
 
 
300
    if (opt7->answer) {
 
301
        /* open the magnitude raster map */
 
302
        mag_fd = Rast_open_old(mag_map, "");
 
303
 
 
304
        mag_raster_type = Rast_get_map_type(mag_fd);
 
305
 
 
306
        /* allocate the cell array */
 
307
        mag_raster_row = Rast_allocate_buf(mag_raster_type);
 
308
    }
 
309
 
 
310
 
 
311
    /* loop through cells, find value, determine direction (n,s,e,w,ne,se,sw,nw),
 
312
       and call appropriate function to draw an arrow on the cell */
 
313
 
 
314
    for (row = 0; row < nrows; row++) {
 
315
        Rast_get_row(layer_fd, raster_row, row, raster_type);
 
316
        ptr = raster_row;
 
317
 
 
318
        if (opt7->answer) {
 
319
            Rast_get_row(mag_fd, mag_raster_row, row, mag_raster_type);
 
320
            mag_ptr = mag_raster_row;
 
321
        }
 
322
 
 
323
        for (col = 0; col < ncols; col++) {
 
324
 
 
325
            if (row % skip != 0)
 
326
                no_arrow = TRUE;
 
327
            else
 
328
                no_arrow = FALSE;
 
329
 
 
330
            if (col % skip != 0)
 
331
                no_arrow = TRUE;
 
332
 
 
333
            /* find aspect direction based on cell value */
 
334
            if (raster_type == CELL_TYPE)
 
335
                aspect_f = *((CELL *) ptr);
 
336
            else if (raster_type == FCELL_TYPE)
 
337
                aspect_f = *((FCELL *) ptr);
 
338
            else if (raster_type == DCELL_TYPE)
 
339
                aspect_f = *((DCELL *) ptr);
 
340
 
 
341
 
 
342
            if (opt7->answer) {
 
343
 
 
344
                if (mag_raster_type == CELL_TYPE)
 
345
                    length = *((CELL *) mag_ptr);
 
346
                else if (mag_raster_type == FCELL_TYPE)
 
347
                    length = *((FCELL *) mag_ptr);
 
348
                else if (mag_raster_type == DCELL_TYPE)
 
349
                    length = *((DCELL *) mag_ptr);
 
350
 
 
351
                length *= scale;
 
352
 
 
353
                if (Rast_is_null_value(mag_ptr, mag_raster_type)) {
 
354
                    G_debug(5, "Invalid arrow length [NULL]. Skipping.");
 
355
                    no_arrow = TRUE;
 
356
                }
 
357
                else if (length <= 0.0) {       /* use fabs() or theta+=180? */
 
358
                    G_debug(5, "Illegal arrow length [%.3f]. Skipping.",
 
359
                            length);
 
360
                    no_arrow = TRUE;
 
361
                }
 
362
            }
 
363
 
 
364
            if (no_arrow) {
 
365
                ptr = G_incr_void_ptr(ptr, Rast_cell_size(raster_type));
 
366
                if (opt7->answer)
 
367
                    mag_ptr =
 
368
                        G_incr_void_ptr(mag_ptr,
 
369
                                        Rast_cell_size(mag_raster_type));
 
370
                no_arrow = FALSE;
 
371
                continue;
 
372
            }
 
373
 
 
374
            /* treat AGNPS and ANSWERS data like old zero-as-null CELL */
 
375
            /*   TODO: update models */
 
376
            if (map_type == 2 || map_type == 3) {
 
377
                if (Rast_is_null_value(ptr, raster_type))
 
378
                    aspect_c = 0;
 
379
                else
 
380
                    aspect_c = (int)(aspect_f + 0.5);
 
381
            }
 
382
 
 
383
 
 
384
            /** Now draw the arrows **/
 
385
 
 
386
            /* case switch for standard GRASS aspect map 
 
387
               measured in degrees counter-clockwise from east */
 
388
            if (map_type == 1) {
 
389
                D_use_color(arrow_color);
 
390
 
 
391
                if (Rast_is_null_value(ptr, raster_type)) {
 
392
                    /* don't draw anything if x_color is none (transparent) */
 
393
                    if (x_color > 0) {
 
394
                        D_use_color(x_color);
 
395
                        draw_x();
 
396
                        D_use_color(arrow_color);
 
397
                    }
 
398
                }
 
399
                else if (aspect_f >= 0.0 && aspect_f <= 360.0) {
 
400
                    if (opt7->answer)
 
401
                        arrow_mag(aspect_f, length);
 
402
                    else
 
403
                        arrow_360(aspect_f);
 
404
                }
 
405
                else if (unknown_color > 0) {
 
406
                    /* don't draw if unknown_color is none (transparent) */
 
407
                    D_use_color(unknown_color);
 
408
                    unknown_();
 
409
                    D_use_color(arrow_color);
 
410
                }
 
411
            }
 
412
 
 
413
 
 
414
            /* case switch for AGNPS type aspect map */
 
415
            else if (map_type == 2) {
 
416
                D_use_color(arrow_color);
 
417
                switch (aspect_c) {
 
418
                case 0:
 
419
                    /* only draw if x_color is not none (transparent) */
 
420
                    if (x_color > 0) {
 
421
                        D_use_color(x_color);
 
422
                        draw_x();
 
423
                        D_use_color(arrow_color);
 
424
                    }
 
425
                    break;
 
426
                case 1:
 
427
                    arrow_n();
 
428
                    break;
 
429
                case 2:
 
430
                    arrow_ne();
 
431
                    break;
 
432
                case 3:
 
433
                    arrow_e();
 
434
                    break;
 
435
                case 4:
 
436
                    arrow_se();
 
437
                    break;
 
438
                case 5:
 
439
                    arrow_s();
 
440
                    break;
 
441
                case 6:
 
442
                    arrow_sw();
 
443
                    break;
 
444
                case 7:
 
445
                    arrow_w();
 
446
                    break;
 
447
                case 8:
 
448
                    arrow_nw();
 
449
                    break;
 
450
                default:
 
451
                    /* only draw if unknown_color is not none */
 
452
                    if (unknown_color > 0) {
 
453
                        D_use_color(unknown_color);
 
454
                        unknown_();
 
455
                        D_use_color(arrow_color);
 
456
                    }
 
457
                    break;
 
458
                }
 
459
            }
 
460
 
 
461
 
 
462
            /* case switch for ANSWERS type aspect map */
 
463
            else if (map_type == 3) {
 
464
                D_use_color(arrow_color);
 
465
                if (aspect_c >= 15 && aspect_c <= 360)  /* start at zero? */
 
466
                    arrow_360((double)aspect_c);
 
467
                else if (aspect_c == 400) {
 
468
                    if (unknown_color > 0) {
 
469
                        /* only draw if unknown_color is not none */
 
470
                        D_use_color(unknown_color);
 
471
                        unknown_();
 
472
                        D_use_color(arrow_color);
 
473
                    }
 
474
                }
 
475
                else if (x_color > 0) {
 
476
                    /* only draw if x_color is not none (transparent) */
 
477
                    D_use_color(x_color);
 
478
                    draw_x();
 
479
                    D_use_color(arrow_color);
 
480
                }
 
481
            }
 
482
 
 
483
            /* case switch for compass type aspect map
 
484
               measured in degrees clockwise from north */
 
485
            else if (map_type == 4) {
 
486
                D_use_color(arrow_color);
 
487
 
 
488
                if (Rast_is_null_value(ptr, raster_type)) {
 
489
                    if (x_color > 0) {
 
490
                        /* only draw if x_color is not none */
 
491
                        D_use_color(x_color);
 
492
                        draw_x();
 
493
                        D_use_color(arrow_color);
 
494
                    }
 
495
                }
 
496
                else if (aspect_f >= 0.0 && aspect_f <= 360.0) {
 
497
                    if (opt7->answer)
 
498
                        arrow_mag(90 - aspect_f, length);
 
499
                    else
 
500
                        arrow_360(90 - aspect_f);
 
501
                }
 
502
                else if (unknown_color > 0) {
 
503
                    /* only draw if unknown_color is not none */
 
504
                    D_use_color(unknown_color);
 
505
                    unknown_();
 
506
                    D_use_color(arrow_color);
 
507
                }
 
508
            }
 
509
 
 
510
            ptr = G_incr_void_ptr(ptr, Rast_cell_size(raster_type));
 
511
            if (opt7->answer)
 
512
                mag_ptr =
 
513
                    G_incr_void_ptr(mag_ptr, Rast_cell_size(mag_raster_type));
 
514
        }
 
515
    }
 
516
 
 
517
    Rast_close(layer_fd);
 
518
    if (opt7->answer)
 
519
        Rast_close(mag_fd);
 
520
 
 
521
    D_save_command(G_recreate_command());
 
522
    D_close_driver();
 
523
 
 
524
    exit(EXIT_SUCCESS);
 
525
}
 
526
 
 
527
/* --- end of main --- */
 
528
 
 
529
/*---------------------------------------------------------------*/
 
530
 
 
531
 
 
532
static void arrow_mag(double theta, double length)
 
533
{                               /* angle is measured in degrees counter-clockwise from east */
 
534
    double x, y, dx, dy, mid_x, mid_y;
 
535
    double theta_offset;
 
536
 
 
537
    theta *= -1;                /* display coords use inverse y */
 
538
 
 
539
    /* find the display coordinates of the middle of the cell */
 
540
    mid_x = col + (.5);
 
541
    mid_y = row + (.5);
 
542
 
 
543
    D_begin();
 
544
 
 
545
    /* tail */
 
546
    D_move_abs(mid_x, mid_y);
 
547
 
 
548
    /* head */
 
549
    x = mid_x + (length * cos(D2R(theta)));
 
550
    y = mid_y + (length * sin(D2R(theta)));
 
551
    D_cont_abs(x, y);
 
552
 
 
553
    /* fin 1 */
 
554
    theta_offset = theta + 20;
 
555
    dx = mid_x + (0.6 * length * cos(D2R(theta_offset)));
 
556
    dy = mid_y + (0.6 * length * sin(D2R(theta_offset)));
 
557
    D_cont_abs(dx, dy);
 
558
 
 
559
    /* fin 2 */
 
560
    D_move_abs(x, y);
 
561
    theta_offset = theta - 20;
 
562
    dx = mid_x + (0.6 * length * cos(D2R(theta_offset)));
 
563
    dy = mid_y + (0.6 * length * sin(D2R(theta_offset)));
 
564
    D_cont_abs(dx, dy);
 
565
 
 
566
    D_end();
 
567
    D_stroke();
 
568
}
 
569
 
 
570
 
 
571
static void arrow_360(double theta)
 
572
{                               /* angle is measured in degrees counter-clockwise from east */
 
573
    double x, y, dx, dy, mid_x, mid_y;
 
574
    double max_radius, theta_offset;
 
575
 
 
576
    theta *= -1;                /* display coords use inverse y */
 
577
    max_radius = 0.8 / 2;
 
578
 
 
579
    /* find the display coordinates of the middle of the cell */
 
580
    mid_x = col + (0.5);
 
581
    mid_y = row + (0.5);
 
582
 
 
583
    D_begin();
 
584
 
 
585
    /* head */
 
586
    x = mid_x + (max_radius * cos(D2R(theta)));
 
587
    y = mid_y + (max_radius * sin(D2R(theta)));
 
588
    D_move_abs(x, y);
 
589
 
 
590
    /* tail */
 
591
    dx = -2 * (max_radius * cos(D2R(theta)));
 
592
    dy = -2 * (max_radius * sin(D2R(theta)));
 
593
    D_cont_rel(dx, dy);
 
594
 
 
595
    /* fin 1 */
 
596
    D_move_abs(x, y);
 
597
    theta_offset = theta + 90;
 
598
    dx = mid_x + (0.5 * max_radius * cos(D2R(theta_offset)));
 
599
    dy = mid_y + (0.5 * max_radius * sin(D2R(theta_offset)));
 
600
    D_cont_abs(dx, dy);
 
601
 
 
602
    /* fin 2 */
 
603
    D_move_abs(x, y);
 
604
    theta_offset = theta - 90;
 
605
    dx = mid_x + (0.5 * max_radius * cos(D2R(theta_offset)));
 
606
    dy = mid_y + (0.5 * max_radius * sin(D2R(theta_offset)));
 
607
    D_cont_abs(dx, dy);
 
608
 
 
609
    D_end();
 
610
    D_stroke();
 
611
}
 
612
 
 
613
static void arrow_se(void)
 
614
{
 
615
    double x = col + (.8);
 
616
    double y = row + (.8);
 
617
    D_begin();
 
618
    D_move_abs(x, y);
 
619
    D_cont_rel(((-.6)), (((-.6))));
 
620
    D_move_abs(x, y);
 
621
    D_cont_rel(0, ((-.4)));
 
622
    D_move_abs(x, y);
 
623
    D_cont_rel(((-.4)), 0);
 
624
    D_end();
 
625
    D_stroke();
 
626
}
 
627
 
 
628
static void arrow_ne(void)
 
629
{
 
630
    double x = col + (.8);
 
631
    double y = row + (.2);
 
632
    D_begin();
 
633
    D_move_abs(x, y);
 
634
    D_cont_rel(((-.6)), (((.6))));
 
635
    D_move_abs(x, y);
 
636
    D_cont_rel(0, ((.4)));
 
637
    D_move_abs(x, y);
 
638
    D_cont_rel(((-.4)), 0);
 
639
    D_end();
 
640
    D_stroke();
 
641
}
 
642
 
 
643
static void arrow_nw(void)
 
644
{
 
645
    double x = col + (.2);
 
646
    double y = row + (.2);
 
647
    D_begin();
 
648
    D_move_abs(x, y);
 
649
    D_cont_rel(((.6)), (((.6))));
 
650
    D_move_abs(x, y);
 
651
    D_cont_rel(0, ((.4)));
 
652
    D_move_abs(x, y);
 
653
    D_cont_rel(((.4)), 0);
 
654
    D_end();
 
655
    D_stroke();
 
656
}
 
657
 
 
658
static void arrow_sw(void)
 
659
{
 
660
    double x = col + (.2);
 
661
    double y = row + (.8);
 
662
    D_begin();
 
663
    D_move_abs(x, y);
 
664
    D_cont_rel(((.6)), (((-.6))));
 
665
    D_move_abs(x, y);
 
666
    D_cont_rel(0, ((-.4)));
 
667
    D_move_abs(x, y);
 
668
    D_cont_rel(((.4)), 0);
 
669
    D_end();
 
670
    D_stroke();
 
671
}
 
672
 
 
673
static void arrow_e(void)
 
674
{
 
675
    double x = col + (.9);
 
676
    double y = row + (.5);
 
677
    D_begin();
 
678
    D_move_abs(x, y);
 
679
    D_cont_rel(((-.8)), 0);
 
680
    D_move_abs(x, y);
 
681
    D_cont_rel(((-.3)), ((-.3)));
 
682
    D_move_abs(x, y);
 
683
    D_cont_rel(((-.3)), ((.3)));
 
684
    D_end();
 
685
    D_stroke();
 
686
}
 
687
 
 
688
static void arrow_w(void)
 
689
{
 
690
    double x = col + (.1);
 
691
    double y = row + (.5);
 
692
    D_begin();
 
693
    D_move_abs(x, y);
 
694
    D_cont_rel(((.8)), 0);
 
695
    D_move_abs(x, y);
 
696
    D_cont_rel(((.3)), ((-.3)));
 
697
    D_move_abs(x, y);
 
698
    D_cont_rel(((.3)), ((.3)));
 
699
    D_end();
 
700
    D_stroke();
 
701
}
 
702
 
 
703
static void arrow_s(void)
 
704
{
 
705
    double x = col + (.5);
 
706
    double y = row + (.9);
 
707
    D_begin();
 
708
    D_move_abs(x, y);
 
709
    D_cont_rel(0, ((-.8)));
 
710
    D_move_abs(x, y);
 
711
    D_cont_rel(((.3)), ((-.3)));
 
712
    D_move_abs(x, y);
 
713
    D_cont_rel(((-.3)), ((-.3)));
 
714
    D_end();
 
715
    D_stroke();
 
716
}
 
717
 
 
718
static void arrow_n(void)
 
719
{
 
720
    double x = col + (.5);
 
721
    double y = row + (.1);
 
722
    D_begin();
 
723
    D_move_abs(x, y);
 
724
    D_cont_rel(0, ((.8)));
 
725
    D_move_abs(x, y);
 
726
    D_cont_rel(((.3)), ((.3)));
 
727
    D_move_abs(x, y);
 
728
    D_cont_rel(((-.3)), ((.3)));
 
729
    D_end();
 
730
    D_stroke();
 
731
}
 
732
 
 
733
static void draw_x(void)
 
734
{
 
735
    double x = col;
 
736
    double y = row;
 
737
    D_begin();
 
738
    D_move_abs(x, y);
 
739
    D_cont_rel(1, 1);
 
740
    y = row + 1;
 
741
    D_move_abs(x, y);
 
742
    D_cont_rel(1, (-1));
 
743
    D_end();
 
744
    D_stroke();
 
745
}
 
746
 
 
747
static void unknown_(void)
 
748
{
 
749
    double x = col + (.3);
 
750
    double y = row + (.4);
 
751
 
 
752
    D_begin();
 
753
    D_move_abs(x, y);
 
754
    D_cont_rel(0, ((-.15)));
 
755
    D_cont_rel(((.1)), ((-.1)));
 
756
    D_cont_rel(((.2)), 0);
 
757
    D_cont_rel(((.1)), ((.1)));
 
758
    D_cont_rel(0, ((.2)));
 
759
    D_cont_rel(((-.1)), ((.1)));
 
760
    D_cont_rel(((-.1)), 0);
 
761
    D_cont_rel(0, ((.25)));
 
762
    D_move_rel(0, ((.1)));
 
763
    D_cont_rel(0, ((.1)));
 
764
    D_end();
 
765
    D_stroke();
 
766
}