|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
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 }