GRASS Programmer's Manual
6.4.2(2012)
|
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 da = 10 * PI / 180; /* later calc from size and tolerance */ 00078 r = elem->coor.arc.r; 00079 G_debug(5, " ARC da = %f r = %f", da, r); 00080 00081 /* convert to positive angles */ 00082 a1 = PI * elem->coor.arc.a1 / 180; 00083 if (a1 < 0) 00084 a1 += 2 * PI; 00085 a2 = PI * elem->coor.arc.a2 / 180; 00086 if (a2 < 0) 00087 a2 += 2 * PI; 00088 00089 if (elem->coor.arc.clock) { /* clockwise */ 00090 while (1) { 00091 x = s * elem->coor.arc.x + s * r * cos(a1); 00092 y = s * elem->coor.arc.y + s * r * sin(a1); 00093 00094 if (rotation != 0.0) 00095 G_rotate_around_point_int(0, 0, &x, &y, rotation); 00096 00097 add_coor(chain, x, y); 00098 if (first) { 00099 x0 = x; 00100 y0 = y; 00101 first = 0; 00102 } 00103 if (a1 == a2) 00104 break; 00105 a1 -= da; 00106 if (a1 < a2) 00107 a1 = a2; 00108 } 00109 00110 } 00111 else { 00112 while (1) { 00113 x = s * elem->coor.arc.x + s * r * cos(a1); 00114 y = s * elem->coor.arc.y + s * r * sin(a1); 00115 00116 if (rotation != 0.0) 00117 G_rotate_around_point_int(0, 0, &x, &y, rotation); 00118 00119 add_coor(chain, x, y); 00120 if (first) { 00121 x0 = x; 00122 y0 = y; 00123 first = 0; 00124 } 00125 if (a1 == a2) 00126 break; 00127 a1 += da; 00128 if (a1 > a2) 00129 a1 = a2; 00130 } 00131 } 00132 break; 00133 } 00134 } 00135 if (part->type == S_POLYGON) { 00136 add_coor(chain, x0, y0); /* Close ring */ 00137 } 00138 00139 return 0; 00140 } 00141 00142 /* 00143 * Stroke symbol to form used for Xdriver. 00144 * 00145 * tolerance currently not supported 00146 */ 00147 void S_stroke(SYMBOL * Symb, int size, double rotation, int tolerance) 00148 { 00149 int i, j; 00150 double s; 00151 SYMBPART *part; 00152 00153 G_debug(3, "S_stroke(): size = %d rotation = %f tolerance = %d", size, 00154 rotation, tolerance); 00155 00156 /* TODO: support for tolerance */ 00157 00158 s = size * Symb->scale; 00159 00160 for (i = 0; i < Symb->count; i++) { 00161 G_debug(4, " part %d", i); 00162 part = Symb->part[i]; 00163 switch (part->type) { 00164 case S_POLYGON: 00165 for (j = 0; j < part->count; j++) { /* RINGS */ 00166 stroke_chain(part, j, s, rotation); 00167 } 00168 break; 00169 case S_STRING: /* string has 1 chain */ 00170 stroke_chain(part, 0, s, rotation); 00171 break; 00172 } 00173 } 00174 }