GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
stroke.c
Go to the documentation of this file.
00001 
00002 /****************************************************************************
00003 *
00004 * MODULE:       Symbol library 
00005 *               
00006 * AUTHOR(S):    Radim Blazek
00007 *
00008 * PURPOSE:      Stroke symbol
00009 *
00010 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00011 *
00012 *               This program is free software under the GNU General Public
00013 *               License (>=v2). Read the file COPYING that comes with GRASS
00014 *               for details.
00015 *
00016 *****************************************************************************/
00017 #include <stdlib.h>
00018 #include <math.h>
00019 #include <grass/gis.h>
00020 #include <grass/symbol.h>
00021 
00022 #define PI M_PI
00023 
00024 void add_coor(SYMBCHAIN * chain, int x, int y)
00025 {
00026     G_debug(5, "    add_coor %d, %d", x, y);
00027     if (chain->scount == chain->salloc) {
00028         chain->salloc += 10;
00029         chain->sx = (int *)G_realloc(chain->sx, chain->salloc * sizeof(int));
00030         chain->sy = (int *)G_realloc(chain->sy, chain->salloc * sizeof(int));
00031     }
00032     chain->sx[chain->scount] = x;
00033     chain->sy[chain->scount] = y;
00034     chain->scount++;
00035 }
00036 
00037 /* draw chain
00038  *   s - scale
00039  *   ch - chain number 
00040  *   rotation - degrees CCW from East
00041  */
00042 int stroke_chain(SYMBPART * part, int ch, double s, double rotation)
00043 {
00044     int k, l, first;
00045     SYMBEL *elem;
00046     SYMBCHAIN *chain;
00047     double r;
00048     double a1, a2, da;
00049     int x, y, x0, y0;
00050 
00051     G_debug(5, "  stroke_chain(): ch = %d", ch);
00052     chain = part->chain[ch];
00053 
00054     G_debug(5, "    element count = %d", chain->count);
00055     first = 1;
00056     for (k = 0; k < chain->count; k++) {
00057         elem = chain->elem[k];
00058         switch (elem->type) {
00059         case S_LINE:
00060             G_debug(5, "    LINE count = %d", elem->coor.line.count);
00061             for (l = 0; l < elem->coor.line.count; l++) {
00062                 x = s * elem->coor.line.x[l];
00063                 y = s * elem->coor.line.y[l];
00064 
00065                 if (rotation != 0.0)
00066                     G_rotate_around_point_int(0, 0, &x, &y, rotation);
00067 
00068                 add_coor(chain, x, y);
00069                 if (first) {
00070                     x0 = x;
00071                     y0 = y;
00072                     first = 0;
00073                 }
00074             }
00075             break;
00076         case S_ARC:
00077             if (s >= 50)
00078                 da = 1 * PI / 180;  /* later calc from size and tolerance */
00079             else
00080                 da = 10 * PI / 180;
00081 
00082             r = elem->coor.arc.r;
00083             G_debug(5, "    ARC da = %f r = %f", da, r);
00084 
00085             /* convert to positive angles */
00086             a1 = PI * elem->coor.arc.a1 / 180;
00087             if (a1 < 0)
00088                 a1 += 2 * PI;
00089             a2 = PI * elem->coor.arc.a2 / 180;
00090             if (a2 < 0)
00091                 a2 += 2 * PI;
00092 
00093             if (elem->coor.arc.clock) { /* clockwise */
00094                 while (1) {
00095                     x = s * elem->coor.arc.x + s * r * cos(a1);
00096                     y = s * elem->coor.arc.y + s * r * sin(a1);
00097 
00098                     if (rotation != 0.0)
00099                         G_rotate_around_point_int(0, 0, &x, &y, rotation);
00100 
00101                     add_coor(chain, x, y);
00102                     if (first) {
00103                         x0 = x;
00104                         y0 = y;
00105                         first = 0;
00106                     }
00107                     if (a1 == a2)
00108                         break;
00109                     a1 -= da;
00110                     if (a1 < a2)
00111                         a1 = a2;
00112                 }
00113 
00114             }
00115             else {
00116                 while (1) {
00117                     x = s * elem->coor.arc.x + s * r * cos(a1);
00118                     y = s * elem->coor.arc.y + s * r * sin(a1);
00119 
00120                     if (rotation != 0.0)
00121                         G_rotate_around_point_int(0, 0, &x, &y, rotation);
00122 
00123                     add_coor(chain, x, y);
00124                     if (first) {
00125                         x0 = x;
00126                         y0 = y;
00127                         first = 0;
00128                     }
00129                     if (a1 == a2)
00130                         break;
00131                     a1 += da;
00132                     if (a1 > a2)
00133                         a1 = a2;
00134                 }
00135             }
00136             break;
00137         }
00138     }
00139     if (part->type == S_POLYGON) {
00140         add_coor(chain, x0, y0);        /* Close ring */
00141     }
00142 
00143     return 0;
00144 }
00145 
00146 /* 
00147  *  Stroke symbol to form used for Xdriver.
00148  *
00149  *  tolerance currently not supported
00150  */
00151 void S_stroke(SYMBOL *Symb, int size, double rotation, int tolerance)
00152 {
00153     int i, j;
00154     double s;
00155     SYMBPART *part;
00156 
00157     G_debug(3, "S_stroke(): size = %d rotation = %f tolerance = %d", size,
00158             rotation, tolerance);
00159 
00160     /* TODO: support for tolerance */
00161 
00162     s = size * Symb->scale;
00163 
00164     for (i = 0; i < Symb->count; i++) {
00165         G_debug(4, "  part %d", i);
00166         part = Symb->part[i];
00167         switch (part->type) {
00168         case S_POLYGON:
00169             for (j = 0; j < part->count; j++) { /* RINGS */
00170                 stroke_chain(part, j, s, rotation);
00171             }
00172             break;
00173         case S_STRING:          /* string has 1 chain */
00174             stroke_chain(part, 0, s, rotation);
00175             break;
00176         }
00177     }
00178 }