1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <math.h>
35 #include <unistd.h>
36
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39
40 #define TRUE 1
41 #define FALSE 0
42
43 #define MAX_CAD 100
44 #define PI M_PI
45 #define CERO 0.00000000001
46
47
48
49 #define COLOR_DEFECTO 2
50 #define ANGULO_DEFECTO 90
51 #define ANCHO_DEFECTO 3
52
53
54 Display *el_display;
55 Window la_ventana;
56 GC el_gc;
57 XEvent el_evento;
58
59 char el_nombre_del_icono[] = "l-system xdraw";
60 char el_nombre_de_la_ventana[] = "l-system xdraw";
61
62
63 struct punto{
64 double x, y, z;
65 };
66
67 typedef struct punto Punto;
68
69 void punto_inicializar(Punto *punto){
70 punto->x = 0.0;
71 punto->y = 0.0;
72 punto->z = 0.0;
73 }
74
75
76
77 #define MAX_PUNTOS 1000
78
79 struct poligono{
80 Punto arreglo[MAX_PUNTOS];
81 int num;
82 };
83
84 typedef struct poligono Poligono;
85
86 void poligono_inicializar(Poligono *poligono){
87 poligono->num = 0;
88 }
89
90 void poligono_adicionar(Poligono *poligono, Punto *punto){
91 poligono->arreglo[poligono->num].x = punto->x;
92 poligono->arreglo[poligono->num].y = punto->y;
93 poligono->arreglo[poligono->num].z = punto->z;
94 poligono->num++;
95 }
96
97 void poligono_dibujar(Poligono *poligono){
98 int i;
99
100
101 for( i = 0; i < poligono->num - 1; i++){
102 XDrawLine(el_evento.xexpose.display, el_evento.xexpose.window, el_gc,
103 poligono->arreglo[i].x,
104 poligono->arreglo[i].y,
105
106 poligono->arreglo[i+1].x,
107 poligono->arreglo[i+1].y);
108 }
109 XDrawLine(el_evento.xexpose.display, el_evento.xexpose.window, el_gc,
110 poligono->arreglo[i].x,
111 poligono->arreglo[i].y,
112
113 poligono->arreglo[0].x,
114 poligono->arreglo[0].y);
115
116
117 }
118
119
120 #define MAX_POLIGONOS 10
121
122 struct pila_poligonos{
123 Poligono arreglo[MAX_POLIGONOS];
124 int num;
125 };
126
127 typedef struct pila_poligonos Pila_poligonos;
128
129 void pila_poligonos_inicializar(Pila_poligonos *pila){
130 pila->num = 0;
131 }
132
133 void pila_poligonos_adicionar(Pila_poligonos *pila){
134 poligono_inicializar(&(pila->arreglo[pila->num]));
135 pila->num++;
136 }
137
138 void pila_poligonos_retirar(Pila_poligonos *pila){
139 pila->num--;
140 }
141
142 Poligono *pila_poligonos_tope(Pila_poligonos *pila){
143 return &(pila->arreglo[pila->num-1]);
144 }
145
146 int esta_pila_poligonos_vacia(Pila_poligonos *pila){
147 return pila->num <= 0;
148 }
149
150 int esta_pila_poligonos_llena(Pila_poligonos *pila){
151 return pila->num >= MAX_POLIGONOS;
152 }
153
154
155 #define MAX_ESTADOS 100000
156
157 struct estado{
158 Punto pos;
159 double angulo;
160 int color;
161 double ancho;
162 };
163
164 typedef struct estado Estado;
165
166 void estado_inicializar(Estado *estado){
167 punto_inicializar(&estado->pos);
168 estado->angulo = 0.0;
169 estado->color = 0.0;
170 estado->ancho = 0.0;
171 }
172
173
174 struct pila_estados{
175 Estado arreglo[MAX_ESTADOS];
176 int num;
177 };
178
179 typedef struct pila_estados Pila_estados;
180
181 void pila_inicializar(Pila_estados *pila){
182 pila->num = 0;
183 }
184
185 void pila_adicionar(Pila_estados *pila, Estado *estado){
186 pila->arreglo[pila->num].pos.x = estado->pos.x;
187 pila->arreglo[pila->num].pos.y = estado->pos.y;
188 pila->arreglo[pila->num].pos.z = estado->pos.z;
189 pila->arreglo[pila->num].angulo = estado->angulo;
190 pila->num++;
191 }
192
193 void pila_retirar(Pila_estados *pila, Estado *estado){
194 pila->num--;
195 estado->pos.x = pila->arreglo[pila->num].pos.x;
196 estado->pos.y = pila->arreglo[pila->num].pos.y;
197 estado->pos.z = pila->arreglo[pila->num].pos.z;
198 estado->angulo = pila->arreglo[pila->num].angulo;
199 }
200
201 int esta_pila_llena(Pila_estados *pila){
202 return pila->num >= MAX_ESTADOS;
203 }
204
205 int esta_pila_vacia(Pila_estados *pila){
206 return pila->num <= 0;
207 }
208
209
210
211 int es_numero(char cad[]){
212 for(; *cad != '\0'; cad++)
213 if(!isdigit(*cad))
214 return 0;
215 return 1;
216 }
217
218 int es_numero_flotante(char cad[]){
219 if(!isdigit(*cad))
220 return 0;
221 for(; isdigit(*cad); cad++){
222 }
223 if(*cad == '.'){
224 cad++;
225 if(!isdigit(*cad))
226 return 0;
227 for(; isdigit(*cad); cad++){
228 }
229 }
230 if(*cad == 'e' || *cad == 'E'){
231 cad++;
232 if(!isdigit(*cad))
233 return 0;
234 for(; isdigit(*cad); cad++){
235 }
236 }
237 if(*cad != '\0'){
238 return 0;
239 }
240 return 1;
241 }
242
243
244 Estado estado_actual;
245 double delta_angulo = 90.0;
246 double delta_pos = 5;
247
248
249 Pila_estados pila_estados;
250 Pila_poligonos pila_poligonos;
251
252 void procesar_comando(char ch){
253 switch(ch){
254 case 'F': {
255 double x_, y_;
256
257
258 x_ = estado_actual.pos.x + delta_pos *
259 cos(estado_actual.angulo*PI/180.0);
260 y_ = estado_actual.pos.y + delta_pos *
261 sin(estado_actual.angulo*PI/180.0);
262
263
264
265 XDrawLine(el_evento.xexpose.display, el_evento.xexpose.window, el_gc,
266 rint(estado_actual.pos.x),rint(estado_actual.pos.y),
267 rint(x_), rint(y_));
268
269
270
271
272
273 estado_actual.pos.x = x_;
274 estado_actual.pos.y = y_;
275 }
276 break;
277 case 'f':{
278
279 estado_actual.pos.x += delta_pos *
280 cos(estado_actual.angulo * PI /180);
281 estado_actual.pos.y += delta_pos *
282 sin(estado_actual.angulo * PI /180);
283
284 }
285 break;
286 case '+':
287 estado_actual.angulo -= delta_angulo;
288
289 break;
290 case '-':
291 estado_actual.angulo += delta_angulo;
292
293 break;
294 case '|':
295 estado_actual.angulo += 180;
296 break;
297 case '[':
298 if(!esta_pila_llena(&pila_estados)){
299 pila_adicionar(&pila_estados,
300 &estado_actual);
301 }
302 else {
303 fprintf(stderr, "Error: La pila"
304 " esta llena\n");
305 exit(3);
306 }
307 break;
308 case ']':
309 if(!esta_pila_vacia(&pila_estados)) {
310 pila_retirar(&pila_estados,
311 &estado_actual);
312 }
313 else{
314 fprintf(stderr, "Error: "
315 "La pila esta vacia\n");
316 exit(4);
317 }
318 break;
319 case '{':
320 if(!esta_pila_poligonos_llena(&pila_poligonos)){
321 pila_poligonos_adicionar(&pila_poligonos);
322 }
323 else{
324 fprintf(stderr, "Error: " "Muchos poligonos\n");
325 exit(5);
326 }
327 break;
328 case '}':
329 if(!esta_pila_poligonos_vacia(&pila_poligonos)){
330 poligono_dibujar(pila_poligonos_tope(&pila_poligonos));
331 pila_poligonos_retirar(&pila_poligonos);
332 }
333 else{
334 fprintf(stderr, "Error:"
335 " no se abrio }\n");
336 exit(6);
337 }
338 break;
339 case '.':
340 if(!esta_pila_poligonos_vacia(&pila_poligonos)){
341 poligono_adicionar(pila_poligonos_tope(&pila_poligonos),
342 &estado_actual.pos);
343 }
344 else{
345 fprintf(stderr, "Error: "
346 " no se ha abierto {\n");
347 exit(7);
348 }
349 break;
350
351
352
353
354
355
356
357
358
359
360
361
362
363 case '!':
364 if(estado_actual.ancho > 1){
365 estado_actual.ancho++;
366 }
367 break;
368 }
369 }
370
371 int main(int argc, char *argv[]){
372 FILE *fp = stdin;
373 char ch;
374
375 char cad[MAX_CAD+1];
376 int i;
377
378 KeySym la_tecla;
379 XSizeHints el_hint;
380 int el_screen;
381 unsigned long el_frente,
382 el_fondo;
383 char el_buffer[8];
384 int contador_teclas;
385 int terminar;
386
387
388
389
390
391 el_display = XOpenDisplay("");
392
393
394 el_screen = DefaultScreen(el_display);
395 el_fondo = WhitePixel( el_display, el_screen);
396 el_frente = BlackPixel( el_display, el_screen);
397 el_hint.x = 100;
398 el_hint.y = 100;
399 el_hint.width = 500;
400 el_hint.height = 500;
401 el_hint.flags = PPosition | PSize;
402 la_ventana = XCreateSimpleWindow ( el_display, DefaultRootWindow(el_display),
403 el_hint.x, el_hint.y, el_hint.width, el_hint.height,
404 7, el_frente, el_fondo);
405
406
407 XSetStandardProperties(el_display, la_ventana, el_nombre_de_la_ventana,
408 el_nombre_del_icono, None, argv, argc, &el_hint);
409
410
411 el_gc = XCreateGC( el_display, la_ventana, 0, 0);
412 XSetBackground( el_display, el_gc, el_fondo);
413 XSetForeground( el_display, el_gc, el_frente);
414
415
416 XSelectInput(el_display, la_ventana, (KeyPressMask | ExposureMask));
417
418
419 XMapRaised(el_display, la_ventana);
420
421
422 pila_inicializar(&pila_estados);
423 pila_poligonos_inicializar(&pila_poligonos);
424 estado_inicializar(&estado_actual);
425 estado_actual.color = COLOR_DEFECTO;
426 estado_actual.ancho = ANCHO_DEFECTO;
427
428
429 if( argc >= 2){
430 if(es_numero(argv[1])){
431 delta_pos = atoi(argv[1]);
432 }
433 else{
434
435 fp = fopen( argv[1], "r");
436 if( fp == NULL){
437 fprintf(stderr, "Error: No se puede abrir el"
438 " archivo \"%s\"\n", argv[1]);
439 return 1;
440 }
441 }
442 }
443
444
445 for( i = 0; (ch = fgetc(fp)) != EOF && isdigit(ch); i++){
446 cad[i] = ch;
447 }
448 if(ch == '.'){
449 cad[i++] = ch;
450 for(; (ch = fgetc(fp)) != EOF && isdigit(ch); i++){
451 cad[i] = ch;
452 }
453 }
454 cad[i] = '\0';
455 if( i > 0){
456 sscanf(cad,"%lf", &delta_angulo);
457 }
458
459
460 estado_actual.pos.x = el_hint.width / 2;
461 estado_actual.pos.y = el_hint.height / 2;
462
463
464
465
466
467
468
469
470
471
472
473 terminar = FALSE;
474 while( !terminar ){
475 XNextEvent(el_display, &el_evento);
476 switch(el_evento.type){
477 case Expose:
478 if(el_evento.xexpose.count == 0){
479
480 do{
481
482 while( isspace(ch) || ch == '\n' || ch == '\r'){
483 ch = fgetc(fp);
484 }
485
486
487
488 procesar_comando(ch);
489 }while( (ch = fgetc(fp)) != EOF);
490 }
491 break;
492 case MappingNotify:
493 XRefreshKeyboardMapping(&el_evento);
494 break;
495 case KeyPress:
496 contador_teclas = XLookupString(&el_evento, el_buffer, 8, &la_tecla, 0);
497 if( (contador_teclas == 1) && (el_buffer[0] == 'q')){
498 terminar = TRUE;
499 }
500 break;
501 }
502 }
503
504
505 XFreeGC(el_display, el_gc);
506 XDestroyWindow(el_display, la_ventana);
507 XCloseDisplay(el_display);
508
509
510 if(fp != stdin){
511 fclose(fp);
512 }
513
514 return 0;
515 }