~ubuntu-branches/ubuntu/wily/grass/wily

« back to all changes in this revision

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

Tags: 7.0.0~rc1+ds1-1~exp1
* New upstream release candidate.
* Repack upstream tarball, remove precompiled Python objects.
* Add upstream metadata.
* Update gbp.conf and Vcs-Git URL to use the experimental branch.
* Update watch file for GRASS 7.0.
* Drop build dependencies for Tcl/Tk, add build dependencies:
  python-numpy, libnetcdf-dev, netcdf-bin, libblas-dev, liblapack-dev
* Update Vcs-Browser URL to use cgit instead of gitweb.
* Update paths to use grass70.
* Add configure options: --with-netcdf, --with-blas, --with-lapack,
  remove --with-tcltk-includes.
* Update patches for GRASS 7.
* Update copyright file, changes:
  - Update copyright years
  - Group files by license
  - Remove unused license sections
* Add patches for various typos.
* Fix desktop file with patch instead of d/rules.
* Use minimal dh rules.
* Bump Standards-Version to 3.9.6, no changes.
* Use dpkg-maintscript-helper to replace directories with symlinks.
  (closes: #776349)
* Update my email to use @debian.org address.

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 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
 
#define MAIN
50
 
static void arrow_mag(double, double);
51
 
static void arrow_360(double);
52
 
static void arrow_se(void);
53
 
static void arrow_ne(void);
54
 
static void arrow_nw(void);
55
 
static void arrow_sw(void);
56
 
static void arrow_e(void);
57
 
static void arrow_w(void);
58
 
static void arrow_s(void);
59
 
static void arrow_n(void);
60
 
static void draw_x(void);
61
 
static void unknown_(void);
62
 
 
63
 
int D_x, D_y;
64
 
double D_ew, D_ns;
65
 
char *mapset;
66
 
char layer_name[128];
67
 
int layer_set;
68
 
int map_type, arrow_color, grid_color, x_color, unknown_color;
69
 
 
70
 
 
71
 
int main(int argc, char **argv)
72
 
{
73
 
    extern double D_ew, D_ns;
74
 
    extern int D_x, D_y;
75
 
    char window_name[128];
76
 
    struct Cell_head window;
77
 
    int t, b, l, r;
78
 
    char full_name[128];
79
 
    RASTER_MAP_TYPE raster_type, mag_raster_type = -1;
80
 
    int layer_fd;
81
 
    void *raster_row, *ptr;
82
 
    int nrows, ncols, row, col;
83
 
    int aspect_c = -1;
84
 
    float aspect_f = -1.0;
85
 
    double ew_res, ns_res;
86
 
    double D_south, D_west;
87
 
    double D_north, D_east;
88
 
    double U_to_D_xconv, U_to_D_yconv;
89
 
    double U_west, U_south;
90
 
    double U_east, U_north;
91
 
    double U_start;
92
 
    double U_x, U_y;
93
 
 
94
 
    double scale;
95
 
    int skip, no_arrow;
96
 
    char *mag_map = NULL, *mag_mapset = NULL;
97
 
    void *mag_raster_row = NULL, *mag_ptr = NULL;
98
 
    double length = -1;
99
 
    int mag_fd = -1;
100
 
    struct FPRange range;
101
 
    double mag_min, mag_max;
102
 
 
103
 
    struct GModule *module;
104
 
    struct Option *opt1, *opt2, *opt3, *opt4, *opt5,
105
 
        *opt6, *opt7, *opt8, *opt9;
106
 
 
107
 
    G_gisinit(argv[0]);
108
 
 
109
 
    module = G_define_module();
110
 
    module->keywords = _("display");
111
 
    module->description =
112
 
        _("Draws arrows representing cell aspect direction "
113
 
          "for a raster map containing aspect data.");
114
 
 
115
 
    opt1 = G_define_option();
116
 
    opt1->key = "map";
117
 
    opt1->type = TYPE_STRING;
118
 
    opt1->required = NO;
119
 
    opt1->multiple = NO;
120
 
    opt1->gisprompt = "old,cell,raster";
121
 
    opt1->description = _("Name of raster aspect map to be displayed");
122
 
 
123
 
    opt2 = G_define_option();
124
 
    opt2->key = "type";
125
 
    opt2->type = TYPE_STRING;
126
 
    opt2->required = NO;
127
 
    opt2->answer = "grass";
128
 
    opt2->options = "grass,compass,agnps,answers";
129
 
    opt2->description = _("Type of existing raster aspect map");
130
 
 
131
 
    opt3 = G_define_option();
132
 
    opt3->key = "arrow_color";
133
 
    opt3->type = TYPE_STRING;
134
 
    opt3->required = NO;
135
 
    opt3->answer = "green";
136
 
    opt3->options = D_COLOR_LIST;
137
 
    opt3->description = _("Color for drawing arrows");
138
 
 
139
 
    opt4 = G_define_option();
140
 
    opt4->key = "grid_color";
141
 
    opt4->type = TYPE_STRING;
142
 
    opt4->required = NO;
143
 
    opt4->answer = "gray";
144
 
    opt4->options = D_COLOR_LIST ",none";
145
 
    opt4->description = _("Color for drawing grid or \"none\"");
146
 
 
147
 
    opt5 = G_define_option();
148
 
    opt5->key = "x_color";
149
 
    opt5->type = TYPE_STRING;
150
 
    opt5->required = NO;
151
 
    opt5->answer = DEFAULT_FG_COLOR;
152
 
    opt5->options = D_COLOR_LIST;
153
 
    opt5->description = _("Color for drawing X's (Null values)");
154
 
 
155
 
    opt6 = G_define_option();
156
 
    opt6->key = "unknown_color";
157
 
    opt6->type = TYPE_STRING;
158
 
    opt6->required = NO;
159
 
    opt6->answer = "red";
160
 
    opt6->options = D_COLOR_LIST;
161
 
    opt6->description = _("Color for showing unknown information");
162
 
 
163
 
    opt9 = G_define_option();
164
 
    opt9->key = "skip";
165
 
    opt9->type = TYPE_INTEGER;
166
 
    opt9->required = NO;
167
 
    opt9->answer = "1";
168
 
    opt9->description = _("Draw arrow every Nth grid cell");
169
 
 
170
 
    opt7 = G_define_option();
171
 
    opt7->key = "magnitude_map";
172
 
    opt7->type = TYPE_STRING;
173
 
    opt7->required = NO;
174
 
    opt7->multiple = NO;
175
 
    opt7->gisprompt = "old,cell,raster";
176
 
    opt7->description =
177
 
        _("Raster map containing values used for arrow length");
178
 
 
179
 
    opt8 = G_define_option();
180
 
    opt8->key = "scale";
181
 
    opt8->type = TYPE_DOUBLE;
182
 
    opt8->required = NO;
183
 
    opt8->answer = "1.0";
184
 
    opt8->description = _("Scale factor for arrows (magnitude map)");
185
 
 
186
 
 
187
 
    /* Check command line */
188
 
    if (G_parser(argc, argv))
189
 
        exit(EXIT_FAILURE);
190
 
 
191
 
 
192
 
    if (opt1->answer) {
193
 
        G_strncpy(layer_name, opt1->answer, sizeof(layer_name) - 1);
194
 
        if ((mapset = G_find_cell2(layer_name, "")) == NULL)
195
 
            G_fatal_error(_("Raster map <%s> not found"), layer_name);
196
 
        layer_set = 1;
197
 
    }
198
 
    else
199
 
        layer_set = 0;
200
 
 
201
 
 
202
 
    arrow_color = D_translate_color(opt3->answer);
203
 
    x_color = D_translate_color(opt5->answer);
204
 
    unknown_color = D_translate_color(opt6->answer);
205
 
 
206
 
    if (strcmp("none", opt4->answer) == 0)
207
 
        grid_color = -1;
208
 
    else
209
 
        grid_color = D_translate_color(opt4->answer);
210
 
 
211
 
 
212
 
    if (strcmp("grass", opt2->answer) == 0)
213
 
        map_type = 1;
214
 
    else if (strcmp("agnps", opt2->answer) == 0)
215
 
        map_type = 2;
216
 
    else if (strcmp("answers", opt2->answer) == 0)
217
 
        map_type = 3;
218
 
    else if (strcmp("compass", opt2->answer) == 0)
219
 
        map_type = 4;
220
 
 
221
 
 
222
 
    scale = atof(opt8->answer);
223
 
    if (scale <= 0.0)
224
 
        G_fatal_error(_("Illegal value for scale factor"));
225
 
 
226
 
    skip = atoi(opt9->answer);
227
 
    if (skip <= 0)
228
 
        G_fatal_error(_("Illegal value for skip factor"));
229
 
 
230
 
 
231
 
    if (opt7->answer) {
232
 
        if (map_type != 1 && map_type != 4)
233
 
            G_fatal_error(_("Magnitude is only supported for GRASS and compass aspect maps."));
234
 
 
235
 
        mag_map = opt7->answer;
236
 
        if ((mag_mapset = G_find_cell2(mag_map, "")) == NULL)
237
 
            G_fatal_error(_("Raster map <%s> not found"), mag_map);
238
 
    }
239
 
    else if (scale != 1.0)
240
 
        G_warning(_("Scale option requires magnitude_map"));
241
 
 
242
 
 
243
 
    /* Setup driver and check important information */
244
 
    if (R_open_driver() != 0)
245
 
        G_fatal_error(_("No graphics device selected"));
246
 
 
247
 
    if (D_get_cur_wind(window_name))
248
 
        G_fatal_error(_("No current window"));
249
 
 
250
 
    if (D_set_cur_wind(window_name))
251
 
        G_fatal_error(_("Current window not available"));
252
 
 
253
 
    /* Read in the map window associated with window */
254
 
    G_get_window(&window);
255
 
 
256
 
    if (D_check_map_window(&window))
257
 
        G_fatal_error(_("Setting map window"));
258
 
 
259
 
    if (G_set_window(&window) == -1)
260
 
        G_fatal_error(_("Current window not settable"));
261
 
 
262
 
    /* Determine conversion factors */
263
 
    if (D_get_screen_window(&t, &b, &l, &r))
264
 
        G_fatal_error(_("Getting screen window"));
265
 
    if (D_do_conversions(&window, t, b, l, r))
266
 
        G_fatal_error(_("Error in calculating conversions"));
267
 
 
268
 
    /* where are we, both geographically and on the screen? */
269
 
    D_south = D_get_d_south();
270
 
    D_north = D_get_d_north();
271
 
    D_east = D_get_d_east();
272
 
    D_west = D_get_d_west();
273
 
 
274
 
    U_west = D_get_u_west();
275
 
    U_east = D_get_u_east();
276
 
    U_south = D_get_u_south();
277
 
    U_north = D_get_u_north();
278
 
 
279
 
    U_to_D_xconv = D_get_u_to_d_xconv();
280
 
    U_to_D_yconv = D_get_u_to_d_yconv();
281
 
 
282
 
    /* number of rows and cols in window */
283
 
    nrows = window.rows;
284
 
    ncols = window.cols;
285
 
 
286
 
    /*
287
 
       if ((nrows > 75) || (ncols > 75)){ 
288
 
       fprintf (stdout,"\n"); 
289
 
       fprintf (stdout,"Current window size:\n"); 
290
 
       fprintf (stdout,"rows:    %d\n", nrows);
291
 
       fprintf (stdout,"columns: %d\n", ncols);
292
 
       fprintf (stdout,"\n"); 
293
 
       fprintf (stdout,"Your current window setting may be too large.\n"); 
294
 
       fprintf (stdout,"Cells displayed on your graphics window may be too\n"); 
295
 
       fprintf (stdout,"small for arrows to be visible.\n\n"); 
296
 
       if (!G_yes("Do you wish to continue", 0))
297
 
       exit(0);
298
 
       }
299
 
     */
300
 
 
301
 
    /* resolutions */
302
 
    ew_res = window.ew_res;
303
 
    ns_res = window.ns_res;
304
 
 
305
 
    /* how many screen units of distance for each cell */
306
 
    D_ew = (D_east - D_west) / ncols;
307
 
    D_ns = (D_south - D_north) / nrows;
308
 
 
309
 
    /* figure out arrow scaling if using a magnitude map */
310
 
    if (opt7->answer) {
311
 
        G_init_fp_range(&range);        /* really needed? */
312
 
        if (G_read_fp_range(mag_map, mag_mapset, &range) != 1)
313
 
            G_fatal_error(_("Problem reading range file"));
314
 
        G_get_fp_range_min_max(&range, &mag_min, &mag_max);
315
 
 
316
 
        scale *= 1.5 * ((D_ew < D_ns) ? D_ew : D_ns) / fabs(mag_max);
317
 
        G_debug(3, "scaling=%.2f  rast_max=%.2f  D_ew=%.2f", scale, mag_max,
318
 
                D_ew);
319
 
    }
320
 
 
321
 
/*------------------------------------------
322
 
    fprintf (stdout,"ew_res:  %.2f\n", window.ew_res);
323
 
    fprintf (stdout,"ns_res:  %.2f\n", window.ns_res);
324
 
    fprintf (stdout,"D_ew:  %f D_ns:  %f \n", D_ew, D_ns); 
325
 
    fprintf (stdout,"nrows:    %d\n", nrows);
326
 
    fprintf (stdout,"ncols:    %d\n", ncols);
327
 
    fprintf (stdout,"t:  %d\n", t);
328
 
    fprintf (stdout,"b:  %d\n", b);
329
 
    fprintf (stdout,"l:  %d\n", l);
330
 
    fprintf (stdout,"r:  %d\n", r);
331
 
    fprintf (stdout,"U_west:    %f\n", U_west);
332
 
    fprintf (stdout,"U_east:    %f\n", U_east);
333
 
    fprintf (stdout,"U_south:   %f\n", U_south);
334
 
    fprintf (stdout,"U_north:   %f\n", U_north);
335
 
    fprintf (stdout,"D_west:    %f\n", D_west);
336
 
    fprintf (stdout,"D_east:    %f\n", D_east);
337
 
    fprintf (stdout,"D_south:   %f\n", D_south);
338
 
    fprintf (stdout,"D_north:   %f\n", D_north);
339
 
    fprintf (stdout,"U_to_D_xconv:      %f\n", U_to_D_xconv);
340
 
    fprintf (stdout,"U_to_D_yconv:      %f\n", U_to_D_yconv);
341
 
--------------------------------------------------------*/
342
 
 
343
 
    if (grid_color > 0) {       /* ie not "none" */
344
 
        /* Set color */
345
 
        R_standard_color(grid_color);
346
 
 
347
 
        /* Draw vertical grids */
348
 
        U_start = U_east;
349
 
        for (U_x = U_start; U_x >= U_west; U_x -= ew_res) {
350
 
            D_x = (int)((U_x - U_west) * U_to_D_xconv + D_west);
351
 
            R_move_abs(D_x, (int)D_south);
352
 
            R_cont_abs(D_x, (int)D_north);
353
 
        }
354
 
 
355
 
        /* Draw horizontal grids */
356
 
        U_start = U_north;
357
 
        for (U_y = U_start; U_y >= U_south; U_y -= ns_res) {
358
 
            D_y = (int)((U_south - U_y) * U_to_D_yconv + D_south);
359
 
            R_move_abs((int)D_west, D_y);
360
 
            R_cont_abs((int)D_east, D_y);
361
 
        }
362
 
    }
363
 
 
364
 
    /* if we didn't get a layer name from the arg options, then
365
 
       get name of layer that is on the screen */
366
 
    if (!layer_set) {
367
 
        if (D_get_cell_name(full_name))
368
 
            G_fatal_error(_("No raster map exists in the current window"));
369
 
 
370
 
        mapset = G_find_cell(full_name, "");
371
 
        if (mapset == NULL)
372
 
            G_fatal_error(_("Raster map <%s> not found"), full_name);
373
 
 
374
 
        sscanf(full_name, "%s", layer_name);
375
 
    }
376
 
 
377
 
    /* open the raster map */
378
 
    layer_fd = G_open_cell_old(layer_name, mapset);
379
 
    if (layer_fd < 0)
380
 
        G_fatal_error(_("Unable to open raster map <%s>"), layer_name);
381
 
 
382
 
    raster_type = G_get_raster_map_type(layer_fd);
383
 
 
384
 
    /* allocate the cell array */
385
 
    raster_row = G_allocate_raster_buf(raster_type);
386
 
 
387
 
 
388
 
    if (opt7->answer) {
389
 
        /* open the magnitude raster map */
390
 
        mag_fd = G_open_cell_old(mag_map, mag_mapset);
391
 
        if (mag_fd < 0)
392
 
            G_fatal_error("Unable to open raster map <%s>", mag_map);
393
 
 
394
 
        mag_raster_type = G_get_raster_map_type(mag_fd);
395
 
 
396
 
        /* allocate the cell array */
397
 
        mag_raster_row = G_allocate_raster_buf(mag_raster_type);
398
 
    }
399
 
 
400
 
 
401
 
    /* loop through cells, find value, determine direction (n,s,e,w,ne,se,sw,nw),
402
 
       and call appropriate function to draw an arrow on the cell */
403
 
 
404
 
    for (row = 0; row < nrows; row++) {
405
 
        G_get_raster_row(layer_fd, raster_row, row, raster_type);
406
 
        ptr = raster_row;
407
 
 
408
 
        if (opt7->answer) {
409
 
            G_get_raster_row(mag_fd, mag_raster_row, row, mag_raster_type);
410
 
            mag_ptr = mag_raster_row;
411
 
        }
412
 
 
413
 
        /* determine screen y coordinate of top of current cell */
414
 
        D_y = (int)(row * D_ns + D_north);
415
 
 
416
 
        for (col = 0; col < ncols; col++) {
417
 
 
418
 
            if (row % skip != 0)
419
 
                no_arrow = TRUE;
420
 
            else
421
 
                no_arrow = FALSE;
422
 
 
423
 
            if (col % skip != 0)
424
 
                no_arrow = TRUE;
425
 
 
426
 
            /* determine screen x coordinate of west side of current cell */
427
 
            D_x = (int)(col * D_ew + D_west);
428
 
 
429
 
            /* find aspect direction based on cell value */
430
 
            if (raster_type == CELL_TYPE)
431
 
                aspect_f = *((CELL *) ptr);
432
 
            else if (raster_type == FCELL_TYPE)
433
 
                aspect_f = *((FCELL *) ptr);
434
 
            else if (raster_type == DCELL_TYPE)
435
 
                aspect_f = *((DCELL *) ptr);
436
 
 
437
 
 
438
 
            if (opt7->answer) {
439
 
 
440
 
                if (mag_raster_type == CELL_TYPE)
441
 
                    length = *((CELL *) mag_ptr);
442
 
                else if (mag_raster_type == FCELL_TYPE)
443
 
                    length = *((FCELL *) mag_ptr);
444
 
                else if (mag_raster_type == DCELL_TYPE)
445
 
                    length = *((DCELL *) mag_ptr);
446
 
 
447
 
                length *= scale;
448
 
 
449
 
                if (G_is_null_value(mag_ptr, mag_raster_type)) {
450
 
                    G_debug(5, "Invalid arrow length [NULL]. Skipping.");
451
 
                    no_arrow = TRUE;
452
 
                }
453
 
                else if (length <= 0.0) {       /* use fabs() or theta+=180? */
454
 
                    G_debug(5, "Illegal arrow length [%.3f]. Skipping.",
455
 
                            length);
456
 
                    no_arrow = TRUE;
457
 
                }
458
 
            }
459
 
 
460
 
            if (no_arrow) {
461
 
                ptr = G_incr_void_ptr(ptr, G_raster_size(raster_type));
462
 
                if (opt7->answer)
463
 
                    mag_ptr =
464
 
                        G_incr_void_ptr(mag_ptr,
465
 
                                        G_raster_size(mag_raster_type));
466
 
                no_arrow = FALSE;
467
 
                continue;
468
 
            }
469
 
 
470
 
            /* treat AGNPS and ANSWERS data like old zero-as-null CELL */
471
 
            /*   TODO: update models */
472
 
            if (map_type == 2 || map_type == 3) {
473
 
                if (G_is_null_value(ptr, raster_type))
474
 
                    aspect_c = 0;
475
 
                else
476
 
                    aspect_c = (int)(aspect_f + 0.5);
477
 
            }
478
 
 
479
 
 
480
 
            /** Now draw the arrows **/
481
 
 
482
 
            /* case switch for standard GRASS aspect map 
483
 
               measured in degrees counter-clockwise from east */
484
 
            if (map_type == 1) {
485
 
                R_standard_color(arrow_color);
486
 
 
487
 
                if (G_is_null_value(ptr, raster_type)) {
488
 
                    R_standard_color(x_color);
489
 
                    draw_x();
490
 
                    R_standard_color(arrow_color);
491
 
                }
492
 
                else if (aspect_f >= 0.0 && aspect_f <= 360.0) {
493
 
                    if (opt7->answer)
494
 
                        arrow_mag(aspect_f, length);
495
 
                    else
496
 
                        arrow_360(aspect_f);
497
 
                }
498
 
                else {
499
 
                    R_standard_color(unknown_color);
500
 
                    unknown_();
501
 
                    R_standard_color(arrow_color);
502
 
                }
503
 
            }
504
 
 
505
 
 
506
 
            /* case switch for AGNPS type aspect map */
507
 
            else if (map_type == 2) {
508
 
                R_standard_color(arrow_color);
509
 
                switch (aspect_c) {
510
 
                case 0:
511
 
                    R_standard_color(x_color);
512
 
                    draw_x();
513
 
                    R_standard_color(arrow_color);
514
 
                    break;
515
 
                case 1:
516
 
                    arrow_n();
517
 
                    break;
518
 
                case 2:
519
 
                    arrow_ne();
520
 
                    break;
521
 
                case 3:
522
 
                    arrow_e();
523
 
                    break;
524
 
                case 4:
525
 
                    arrow_se();
526
 
                    break;
527
 
                case 5:
528
 
                    arrow_s();
529
 
                    break;
530
 
                case 6:
531
 
                    arrow_sw();
532
 
                    break;
533
 
                case 7:
534
 
                    arrow_w();
535
 
                    break;
536
 
                case 8:
537
 
                    arrow_nw();
538
 
                    break;
539
 
                default:
540
 
                    R_standard_color(unknown_color);
541
 
                    unknown_();
542
 
                    R_standard_color(arrow_color);
543
 
                    break;
544
 
                }
545
 
            }
546
 
 
547
 
 
548
 
            /* case switch for ANSWERS type aspect map */
549
 
            else if (map_type == 3) {
550
 
                R_standard_color(arrow_color);
551
 
                if (aspect_c >= 15 && aspect_c <= 360)  /* start at zero? */
552
 
                    arrow_360((double)aspect_c);
553
 
                else if (aspect_c == 400) {
554
 
                    R_standard_color(unknown_color);
555
 
                    unknown_();
556
 
                    R_standard_color(arrow_color);
557
 
                }
558
 
                else {
559
 
                    R_standard_color(x_color);
560
 
                    draw_x();
561
 
                    R_standard_color(arrow_color);
562
 
                }
563
 
            }
564
 
 
565
 
            /* case switch for compass type aspect map
566
 
               measured in degrees clockwise from north */
567
 
            else if (map_type == 4) {
568
 
                R_standard_color(arrow_color);
569
 
 
570
 
                if (G_is_null_value(ptr, raster_type)) {
571
 
                    R_standard_color(x_color);
572
 
                    draw_x();
573
 
                    R_standard_color(arrow_color);
574
 
                }
575
 
                else if (aspect_f >= 0.0 && aspect_f <= 360.0) {
576
 
                    if (opt7->answer)
577
 
                        arrow_mag(90 - aspect_f, length);
578
 
                    else
579
 
                        arrow_360(90 - aspect_f);
580
 
                }
581
 
                else {
582
 
                    R_standard_color(unknown_color);
583
 
                    unknown_();
584
 
                    R_standard_color(arrow_color);
585
 
                }
586
 
            }
587
 
 
588
 
            ptr = G_incr_void_ptr(ptr, G_raster_size(raster_type));
589
 
            if (opt7->answer)
590
 
                mag_ptr =
591
 
                    G_incr_void_ptr(mag_ptr, G_raster_size(mag_raster_type));
592
 
        }
593
 
    }
594
 
 
595
 
    G_close_cell(layer_fd);
596
 
    if (opt7->answer)
597
 
        G_close_cell(mag_fd);
598
 
    D_add_to_list(G_recreate_command());
599
 
    R_close_driver();
600
 
 
601
 
    exit(0);
602
 
}
603
 
 
604
 
/* --- end of main --- */
605
 
 
606
 
/*---------------------------------------------------------------*/
607
 
 
608
 
 
609
 
static void arrow_mag(double theta, double length)
610
 
{                               /* angle is measured in degrees counter-clockwise from east */
611
 
    extern double D_ew, D_ns;
612
 
    extern int D_x, D_y;
613
 
    int x, y, dx, dy, mid_x, mid_y;
614
 
    double theta_offset;
615
 
 
616
 
    theta *= -1;                /* display coords use inverse y */
617
 
 
618
 
    /* find the display coordinates of the middle of the cell */
619
 
    mid_x = D_x + (int)(D_ew * .5);
620
 
    mid_y = D_y + (int)(D_ns * .5);
621
 
 
622
 
    /* tail */
623
 
    R_move_abs(mid_x, mid_y);
624
 
 
625
 
    /* head */
626
 
    x = mid_x + (int)(length * cos(D2R(theta)));
627
 
    y = mid_y + (int)(length * sin(D2R(theta)));
628
 
    R_cont_abs(x, y);
629
 
 
630
 
    /* fin 1 */
631
 
    theta_offset = theta + 20;
632
 
    dx = mid_x + (int)(0.6 * length * cos(D2R(theta_offset)));
633
 
    dy = mid_y + (int)(0.6 * length * sin(D2R(theta_offset)));
634
 
    R_cont_abs(dx, dy);
635
 
 
636
 
    /* fin 2 */
637
 
    R_move_abs(x, y);
638
 
    theta_offset = theta - 20;
639
 
    dx = mid_x + (int)(0.6 * length * cos(D2R(theta_offset)));
640
 
    dy = mid_y + (int)(0.6 * length * sin(D2R(theta_offset)));
641
 
    R_cont_abs(dx, dy);
642
 
}
643
 
 
644
 
 
645
 
static void arrow_360(double theta)
646
 
{                               /* angle is measured in degrees counter-clockwise from east */
647
 
    extern double D_ew, D_ns;
648
 
    extern int D_x, D_y;
649
 
    int x, y, dx, dy, mid_x, mid_y;
650
 
    double max_radius, theta_offset;
651
 
 
652
 
    theta *= -1;                /* display coords use inverse y */
653
 
    max_radius = ((D_ew < D_ns) ? D_ew : D_ns) * 0.8 / 2;
654
 
 
655
 
    /* find the display coordinates of the middle of the cell */
656
 
    mid_x = D_x + (int)(D_ew * 0.5);
657
 
    mid_y = D_y + (int)(D_ns * 0.5);
658
 
 
659
 
    /* head */
660
 
    x = mid_x + (int)(max_radius * cos(D2R(theta)));
661
 
    y = mid_y + (int)(max_radius * sin(D2R(theta)));
662
 
    R_move_abs(x, y);
663
 
 
664
 
    /* tail */
665
 
    dx = -2 * (int)(max_radius * cos(D2R(theta)));
666
 
    dy = -2 * (int)(max_radius * sin(D2R(theta)));
667
 
    R_cont_rel(dx, dy);
668
 
 
669
 
    /* fin 1 */
670
 
    R_move_abs(x, y);
671
 
    theta_offset = theta + 90;
672
 
    dx = mid_x + (int)(0.5 * max_radius * cos(D2R(theta_offset)));
673
 
    dy = mid_y + (int)(0.5 * max_radius * sin(D2R(theta_offset)));
674
 
    R_cont_abs(dx, dy);
675
 
 
676
 
    /* fin 2 */
677
 
    R_move_abs(x, y);
678
 
    theta_offset = theta - 90;
679
 
    dx = mid_x + (int)(0.5 * max_radius * cos(D2R(theta_offset)));
680
 
    dy = mid_y + (int)(0.5 * max_radius * sin(D2R(theta_offset)));
681
 
    R_cont_abs(dx, dy);
682
 
 
683
 
}
684
 
 
685
 
static void arrow_se(void)
686
 
{
687
 
    extern double D_ew, D_ns;
688
 
    extern int D_x, D_y;
689
 
    int x, y;
690
 
 
691
 
    x = D_x + (int)(D_ew * .8);
692
 
    y = D_y + (int)(D_ns * .8);
693
 
    R_move_abs(x, y);
694
 
    R_cont_rel((int)(D_ew * (-.6)), ((int)(D_ns * (-.6))));
695
 
    R_move_abs(x, y);
696
 
    R_cont_rel(0, (int)(D_ns * (-.4)));
697
 
    R_move_abs(x, y);
698
 
    R_cont_rel((int)(D_ew * (-.4)), 0);
699
 
 
700
 
}
701
 
 
702
 
static void arrow_ne(void)
703
 
{
704
 
    extern double D_ew, D_ns;
705
 
    extern int D_x, D_y;
706
 
    int x, y;
707
 
 
708
 
    x = D_x + (int)(D_ew * .8);
709
 
    y = D_y + (int)(D_ns * .2);
710
 
    R_move_abs(x, y);
711
 
    R_cont_rel((int)(D_ew * (-.6)), ((int)(D_ns * (.6))));
712
 
    R_move_abs(x, y);
713
 
    R_cont_rel(0, (int)(D_ns * (.4)));
714
 
    R_move_abs(x, y);
715
 
    R_cont_rel((int)(D_ew * (-.4)), 0);
716
 
 
717
 
}
718
 
 
719
 
static void arrow_nw(void)
720
 
{
721
 
    extern double D_ew, D_ns;
722
 
    extern int D_x, D_y;
723
 
    int x, y;
724
 
 
725
 
    x = D_x + (int)(D_ew * .2);
726
 
    y = D_y + (int)(D_ns * .2);
727
 
    R_move_abs(x, y);
728
 
    R_cont_rel((int)(D_ew * (.6)), ((int)(D_ns * (.6))));
729
 
    R_move_abs(x, y);
730
 
    R_cont_rel(0, (int)(D_ns * (.4)));
731
 
    R_move_abs(x, y);
732
 
    R_cont_rel((int)(D_ew * (.4)), 0);
733
 
 
734
 
}
735
 
 
736
 
static void arrow_sw(void)
737
 
{
738
 
    extern double D_ew, D_ns;
739
 
    extern int D_x, D_y;
740
 
    int x, y;
741
 
 
742
 
    x = D_x + (int)(D_ew * .2);
743
 
    y = D_y + (int)(D_ns * .8);
744
 
    R_move_abs(x, y);
745
 
    R_cont_rel((int)(D_ew * (.6)), ((int)(D_ns * (-.6))));
746
 
    R_move_abs(x, y);
747
 
    R_cont_rel(0, (int)(D_ns * (-.4)));
748
 
    R_move_abs(x, y);
749
 
    R_cont_rel((int)(D_ew * (.4)), 0);
750
 
 
751
 
}
752
 
static void arrow_e(void)
753
 
{
754
 
    extern double D_ew, D_ns;
755
 
    extern int D_x, D_y;
756
 
    int x, y;
757
 
 
758
 
    x = D_x + (int)(D_ew * .9);
759
 
    y = D_y + (int)(D_ns * .5);
760
 
    R_move_abs(x, y);
761
 
    R_cont_rel((int)(D_ew * (-.8)), 0);
762
 
    R_move_abs(x, y);
763
 
    R_cont_rel((int)(D_ew * (-.3)), (int)(D_ns * (-.3)));
764
 
    R_move_abs(x, y);
765
 
    R_cont_rel((int)(D_ew * (-.3)), (int)(D_ns * (.3)));
766
 
 
767
 
}
768
 
static void arrow_w(void)
769
 
{
770
 
    extern double D_ew, D_ns;
771
 
    extern int D_x, D_y;
772
 
    int x, y;
773
 
 
774
 
    x = D_x + (int)(D_ew * .1);
775
 
    y = D_y + (int)(D_ns * .5);
776
 
    R_move_abs(x, y);
777
 
    R_cont_rel((int)(D_ew * (.8)), 0);
778
 
    R_move_abs(x, y);
779
 
    R_cont_rel((int)(D_ew * (.3)), (int)(D_ns * (-.3)));
780
 
    R_move_abs(x, y);
781
 
    R_cont_rel((int)(D_ew * (.3)), (int)(D_ns * (.3)));
782
 
 
783
 
}
784
 
static void arrow_s(void)
785
 
{
786
 
    extern double D_ew, D_ns;
787
 
    extern int D_x, D_y;
788
 
    int x, y;
789
 
 
790
 
    x = D_x + (int)(D_ew * .5);
791
 
    y = D_y + (int)(D_ns * .9);
792
 
    R_move_abs(x, y);
793
 
    R_cont_rel(0, (int)(D_ns * (-.8)));
794
 
    R_move_abs(x, y);
795
 
    R_cont_rel((int)(D_ew * (.3)), (int)(D_ns * (-.3)));
796
 
    R_move_abs(x, y);
797
 
    R_cont_rel((int)(D_ew * (-.3)), (int)(D_ns * (-.3)));
798
 
 
799
 
}
800
 
static void arrow_n(void)
801
 
{
802
 
    extern double D_ew, D_ns;
803
 
    extern int D_x, D_y;
804
 
    int x, y;
805
 
 
806
 
    x = D_x + (int)(D_ew * .5);
807
 
    y = D_y + (int)(D_ns * .1);
808
 
    R_move_abs(x, y);
809
 
    R_cont_rel(0, (int)(D_ns * (.8)));
810
 
    R_move_abs(x, y);
811
 
    R_cont_rel((int)(D_ew * (.3)), (int)(D_ns * (.3)));
812
 
    R_move_abs(x, y);
813
 
    R_cont_rel((int)(D_ew * (-.3)), (int)(D_ns * (.3)));
814
 
 
815
 
}
816
 
static void draw_x(void)
817
 
{
818
 
    extern double D_ew, D_ns;
819
 
    extern int D_x, D_y;
820
 
    int x, y;
821
 
 
822
 
    x = D_x;
823
 
    y = D_y;
824
 
    R_move_abs(x, y);
825
 
    R_cont_rel((int)D_ew, (int)D_ns);
826
 
    y = D_y + (int)D_ns;
827
 
    R_move_abs(x, y);
828
 
    R_cont_rel((int)D_ew, (int)(D_ns * -1));
829
 
}
830
 
static void unknown_(void)
831
 
{
832
 
    extern double D_ew, D_ns;
833
 
    extern int D_x, D_y;
834
 
    int x, y;
835
 
 
836
 
    x = D_x + (int)(D_ew * .3);
837
 
    y = D_y + (int)(D_ns * .4);
838
 
    R_move_abs(x, y);
839
 
    R_cont_rel(0, (int)(D_ns * (-.15)));
840
 
    R_cont_rel((int)(D_ew * (.1)), (int)(D_ns * (-.1)));
841
 
    R_cont_rel((int)(D_ew * (.2)), 0);
842
 
    R_cont_rel((int)(D_ew * (.1)), (int)(D_ns * (.1)));
843
 
    R_cont_rel(0, (int)(D_ns * (.2)));
844
 
    R_cont_rel((int)(D_ew * (-.1)), (int)(D_ns * (.1)));
845
 
    R_cont_rel((int)(D_ew * (-.1)), 0);
846
 
    R_cont_rel(0, (int)(D_ns * (.25)));
847
 
    R_move_rel(0, (int)(D_ns * (.1)));
848
 
    R_cont_rel(0, (int)(D_ns * (.1)));
849
 
}