Annotation of QuadraticMandel/genfractal.c, revision 1.2
1.1 cvsmgr 1: /*******************************************************************************
1.2 ! cvsmgr 2: +* Fractal set generation for quadratic maps.
! 3: +* Copyright (C) 2011, Raúl Durán Díaz, raul.duran@uah.es
! 4: +*
! 5: +* This program is free software: you can redistribute it and/or modify
! 6: +* it under the terms of the GNU General Public License as published by
! 7: +* the Free Software Foundation, either version 3 of the License, or
! 8: +* (at your option) any later version.
! 9: +*
! 10: +* This program is distributed in the hope that it will be useful,
! 11: +* but WITHOUT ANY WARRANTY; without even the implied warranty of
! 12: +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 13: +* GNU General Public License for more details.
! 14: +*
! 15: +* You should have received a copy of the GNU General Public License
! 16: +* along with this program. If not, see <http://www.gnu.org/licenses/>.
! 17: *******************************************************************************/
! 18: /*******************************************************************************
1.1 cvsmgr 19: +*
20: +* 9.12.2005
21: +*
22: +* $Id: genfractal.c,v 1.24 2010/03/16 17:42:39 rduran Exp $
23: +* $Name: $
24: +*
25: +* Falta por hacer el cálculo del mínimo A para Gc. Ahora se usa la
26: +* iteración especial con valor de 50.0
27: +*
28: *******************************************************************************/
29: # include <stdlib.h>
30: # include <stdio.h>
31: # include <string.h>
32: # include <math.h>
33: # include <stdarg.h>
34: # include "mypng.h"
35: # include "genfractal.h"
36: # include "mathutil.h"
37:
38: enum Zona {ZONA_Fbc_MAS, ZONA_Fbc_MENOS, ZONA_Fc_MAS, ZONA_Fc_MENOS, ZONA_Gc, ZONA_00};
39:
40: static double minA = 1.0;
41: static double a1 = 1.0;
42: static double b1 = 1.0;
43: static double c1 = 1.0;
44: static double a2 = 1.0;
45: static double b2 = 1.0;
46: static double c2 = 1.0;
47:
48: enum Zona zona = ZONA_Fbc_MAS;
49:
50: /*******************************************************************************
51: +* El siguiente if a 1 para imagen en color, 0 para blanco y negro.
52: *******************************************************************************/
53: # if 1
54: static void PNGColorAssign(png_colorp p, int iter, int itermax)
55: {
56: double ratio = 767.0*((double) iter / (double) itermax);
57: int c = lround(ratio);
58:
59: # if 0
60: if (c != 0 && c != 767) printf("iter: %d, ratio=%lf, c=%d\n", iter, ratio, c);
61: # endif
62: switch (c/256)
63: {
64: case 0:
65: p->blue = c%256;
66: # if 0
67: if (c!=0 && c!=255) printf("Caso 0\n");
68: # endif
69: break;
70:
71: case 1:
72: p->blue = 255 - c%256;
73: p->green = c%256;
74: # if 0
75: if (c!=0 && c!=255) printf("Caso 1\n");
76: # endif
77: break;
78:
79: default:
80: p->green = 255 - c%256;
81: p->red = c%256;
82: # if 0
83: if (c!=0 && c!=255) printf("Caso default\n");
84: # endif
85: }
86: }
87: # endif
88:
89: /*******************************************************************************
90: +* El siguiente if a 0 para imagen en color, 1 para blanco y negro.
91: *******************************************************************************/
92: # if 0
93: static void PNGColorAssign(png_colorp p, int iter, int itermax)
94: {
95: double ratio = 255.0*((double) iter / (double) itermax);
96:
97: /*******************************************************************************
98: +* El siguiente if a 1 para fondo blanco, fractal negro.
99: *******************************************************************************/
100: # if 1
101: p->blue = p->green = p->red = 255 - lround(ratio);
102: # endif
103: /*******************************************************************************
104: +* El siguiente if a 1 para fondo negro, fractal blanco.
105: *******************************************************************************/
106: # if 0
107: p->blue = p->green = p->red = lround(ratio);
108: # endif
109: }
110: # endif
111:
112: static double ComputeZR(double zr, double zi)
113: {
114: return a1*zr*zr + 2.0*b1*zr*zi + c1*zi*zi;
115: }
116:
117: static double ComputeZI(double zr, double zi)
118: {
119: return a2*zr*zr + 2.0*b2*zr*zi + c2*zi*zi;
120: }
121:
122: static double maximo(double a, double b)
123: {
124: if (a > b)
125: return a;
126: else
127: return b;
128: }
129:
130: static double minimo(double a, double b)
131: {
132: if (a < b)
133: return a;
134: else
135: return b;
136: }
137:
138: /*******************************************************************************
139: +* Función A_t para la parte F^+_{bc}
140: *******************************************************************************/
141: static double Ap_t(double t)
142: {
143: return pow(1. - pow(t,2),2)/pow(1. + pow(t,2),2) +
144: pow(t,2)/pow(1. + pow(t,2),2)*
145: (
146: pow(c1,2)*pow(t,2) +
147: 4.*pow(b1,2) +
148: 4.*b1*c1*t
149: );
150: }
151:
152:
153: static void ComputeMinAplus00(void)
154: {
155: double t = sqrt(2./(2.+pow(c1,2)));
156:
157: minA = minimo(minA, Ap_t(t));
158: minA = minimo(minA, Ap_t(-t));
159:
160: return;
161: }
162:
163: void ComputeMinAplus(void)
164: {
165: double k;
166: double p;
167: double q;
168: double d;
169: double rho;
170: double theta;
171: double l1q;
172: double l2q;
173: int i;
174:
175: k = (pow(c1,2)-2.*pow(b1,2)+2.)/(3.*b1*c1);
176: p = (-4.*k-3.*b1*c1-2.*pow(c1,2)*k+3.*b1*c1*pow(k,2)+4.*pow(b1,2)*k)/(b1*c1);
177: q = (-2.*pow(k,2)-3.*b1*c1*k+2+b1*c1*pow(k,3)-2.*pow(b1,2)+2.*pow(b1,2)*pow(k,2)-pow(c1,2)*pow(k,2))/(b1*c1);
178:
179: if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
180: {
181: l1q = q*q/4.;
182: l2q = -d/324.;
183: rho = sqrt(l1q + l2q);
184: theta = atan(sqrt(l2q/l1q));
185:
186: for (i = 0; i < 3; i++)
187: minA = minimo(minA, Ap_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
188: }
189: else
190: {
191: fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
192: minA = minimo(minA, Ap_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
193: }
194:
195: return;
196: }
197:
198: /*******************************************************************************
199: +* Función A_t para la parte F^-_{bc}
200: *******************************************************************************/
201: static double Am_t(double t)
202: {
203: return 1 + pow(t,2)/pow(1. + pow(t,2),2)*
204: (
205: pow(c1,2)*pow(t,2) +
206: 4.*pow(b1,2) +
207: 4.*b1*c1*t
208: );
209: }
210:
211: static void ComputeMinAminus00(void)
212: {
213: if (b1 != 0.0)
214: {
215: minA = minimo(minA, Am_t(1.));
216: minA = minimo(minA, Am_t(-1.));
217: }
218:
219: return;
220: }
221:
222: static void ComputeMinAminus(void)
223: {
224: double k;
225: double p;
226: double q;
227: double d;
228: double rho;
229: double theta;
230: double l1q;
231: double l2q;
232: int i;
233:
234: k = (pow(c1,2)-2.*pow(b1,2))/(3.*b1*c1);
235: p = (4.*pow(b1,2)*k-2.*pow(c1,2)*k+3.*b1*c1*pow(k,2)-3.*b1*c1)/(b1*c1);
236: q = (-2.*pow(b1,2)+2.*pow(b1,2)*pow(k,2)-pow(c1,2)*pow(k,2)+b1*c1*pow(k,3)-3.*b1*c1*k)/(b1*c1);
237:
238: if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
239: {
240: l1q = q*q/4.;
241: l2q = -d/324.;
242: rho = sqrt(l1q + l2q);
243: theta = atan(sqrt(l2q/l1q));
244:
245: for (i = 0; i < 3; i++)
246: minA = minimo(minA, Am_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
247: }
248: else
249: {
250: fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
251: minA = minimo(minA, Am_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
252: }
253:
254: return;
255: }
256:
257: /*******************************************************************************
258: +* Función A_t y sus derivadas para la parte F^+_{c}
259: *******************************************************************************/
260: static double AFcMas_t(double t)
261: {
262: return 1/pow(1. + pow(t,2),2)*
263: (
264: pow(c1,2)*pow(t,4) +
265: 4.*c1*pow(t,3) +
266: 4.*pow(t,2) +
267: 1.
268: );
269: }
270:
271: static void ComputeMinAFcMas0(void)
272: {
273:
274: minA = minimo(minA, AFcMas_t(sqrt(2.)/.2));
275: minA = minimo(minA, AFcMas_t(-sqrt(2.)/.2));
276:
277: return;
278: }
279:
280: static void ComputeMinAFcMas(void)
281: {
282: double k;
283: double p;
284: double q;
285: double d;
286: double rho;
287: double theta;
288: double l1q;
289: double l2q;
290: int i;
291:
292: k = 1./3.*(pow(c1,2)-2.)/c1;
293: p = (-2.*k*pow(c1,2) + 4.*k + 3.*c1*pow(k,2) - 3.*c1)/c1;
294: q = (-1. - pow(c1,2)*pow(k,2) + 2.*pow(k,2) + c1*pow(k,3) - 3.*c1*k)/c1;
295:
296: if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
297: {
298: l1q = q*q/4.;
299: l2q = -d/324.;
300: rho = sqrt(l1q + l2q);
301: theta = atan(sqrt(l2q/l1q));
302:
303: for (i = 0; i < 3; i++)
304: minA = minimo(minA, AFcMas_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
305: }
306: else
307: {
308: fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
309: minA = minimo(minA, AFcMas_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
310: }
311:
312: return;
313: }
314:
315: /*******************************************************************************
316: +* Función A_t y sus derivadas para la parte F^-_{c}
317: *******************************************************************************/
318: static double AFcMenos_t(double t)
319: {
320: return 1/pow(1. + pow(t,2),2)*
321: (
322: pow(c1,2)*pow(t,4) -
323: 4.*c1*pow(t,3) +
324: 4.*pow(t,2) +
325: 1.
326: );
327: }
328:
329: static void ComputeMinAFcMenos0(void)
330: {
331:
332: minA = minimo(minA, AFcMenos_t(sqrt(2.)/.2));
333: minA = minimo(minA, AFcMenos_t(-sqrt(2.)/.2));
334:
335: return;
336: }
337:
338: static void ComputeMinAFcMenos(void)
339: {
340: double k;
341: double p;
342: double q;
343: double d;
344: double rho;
345: double theta;
346: double l1q;
347: double l2q;
348: int i;
349:
350: k = -1./3.*(pow(c1,2)-2.)/c1;
351: p = (2.*k*pow(c1,2) - 4.*k + 3.*c1*pow(k,2) - 3.*c1)/c1;
352: q = (1. + pow(c1,2)*pow(k,2) - 2.*pow(k,2) + c1*pow(k,3) - 3.*c1*k)/c1;
353:
354: if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
355: {
356: l1q = q*q/4.;
357: l2q = -d/324.;
358: rho = sqrt(l1q + l2q);
359: theta = atan(sqrt(l2q/l1q));
360:
361: for (i = 0; i < 3; i++)
362: minA = minimo(minA, AFcMenos_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
363: }
364: else
365: {
366: fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
367: minA = minimo(minA, AFcMenos_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
368: }
369:
370: return;
371: }
372:
373: /*******************************************************************************
374: +* Función para la parte G_{c}
375: *******************************************************************************/
376: static void ComputeMinAGc(void)
377: {
378: double ypsilon;
379: double Ypsilon;
380: double tau1;
381:
382: ypsilon = 3*pow(c1,9) - 9*pow(c1,8) + 36*pow(c1,7) -
383: 111*pow(c1,6) + 540*pow(c1,5) - 1107*pow(c1,4) +
384: 2592*pow(c1,3) - 3321*pow(c1,2) + 6237*c1-10044;
385:
386: if (ypsilon > 0.0)
387: {
388: Ypsilon = pow((c1-1.)*pow(c1+1.,2) + sqrt(ypsilon)/9., 1./3.);
389: tau1 = (3*pow(Ypsilon,2) + 3*(1-c1)*Ypsilon -
390: (pow(c1,3)-pow(c1,2)+3*c1-15))/(3*c1*Ypsilon);
391: }
392: }
393:
394: /*******************************************************************************
395: +* Cálculo del mínimo de la B y computación del Modúlo máximo.
396: *******************************************************************************/
397:
398: static double ComputeMod2Max(double alpha, double beta)
399: {
400: double minB = 0.0;
401:
402: if (zona == ZONA_Fbc_MAS)
403: minB = c1*alpha - sqrt(pow(2.*b1*alpha,2)+pow(2.*beta-c1*alpha,2));
404: else if (zona == ZONA_Fbc_MENOS)
405: minB = c1*alpha+2.*beta - sqrt(pow(2.*b1*alpha,2)+pow(c1*alpha,2));
406: else if (zona == ZONA_Fc_MAS)
407: minB = beta + alpha*c1 - sqrt(pow(beta-alpha*c1,2) + 4.*pow(alpha,2));
408: else if (zona == ZONA_Fc_MENOS)
409: minB = beta + alpha*c1 - sqrt(pow(beta-alpha*c1,2) + 4.*pow(alpha,2));
410: else if (zona == ZONA_Gc)
411: minB = alpha*(c1 + 1.) - sqrt(pow(-c1+1.,2)*pow(alpha,2)+4.*pow(alpha-beta,2));
412: else if (zona == ZONA_00)
413: minB = -2.*sqrt(pow(alpha,2) + pow(beta,2));
414: else
415: {
416: fprintf(stderr, "#ERROR: Zona no implementada en el cálculo de min B.\n");
417: return 0.;
418: }
419:
420: return maximo(0., (1.-minB)/minA);
421: }
422:
423: /*******************************************************************************
424: +* Parte fija del cómputo.
425: *******************************************************************************/
426: static void IterComputation(png_colorpp image, int itermax)
427: {
428: int row, col, iter;
429: double mod2;
430: double mod2max;
431: double zrtemp, zitemp;
432: double zr, zi;
433: double cr, ci;
434: # if 0
435: png_color p;
436: # endif
437:
438: for (row = 0; row < NUM_ROWS; row++)
439: {
440: for (col = 0; col < NUM_COLS; col++)
441: {
442: cr = PixToCoordX(col);
443: ci = PixToCoordY(row);
444:
445: mod2max = ComputeMod2Max(cr, ci);
446:
447: zr = 0.0;
448: zi = 0.0;
449:
450: for (iter = 0; iter < itermax; iter++)
451: {
452: zrtemp = ComputeZR(zr, zi);
453: zitemp = ComputeZI(zr, zi);
454:
455: zr = zrtemp + cr;
456: zi = zitemp + ci;
457:
458: mod2 = zr*zr + zi*zi;
459: if (mod2 > mod2max)
460: {
461: # if 0
462: printf("Nos salimos en la: %d\n", iter);
463: # endif
464: break;
465: }
466: }
467: # if 0
468: if (iter >= itermax)
469: printf("Nos salimos por exceso, en (%lf, %lf)\n", cr, ci);
470: # endif
471:
472: PNGColorAssign(&image[row][col], iter, itermax);
473: }
474: }
475:
476: # if 0
477: p.red = 0; p.green = 255; p.blue = 0;
478: DrawHorizLine(image, 0.0, p);
479: DrawHorizLine(image, 1.0, p);
480: DrawHorizLine(image, -1.0, p);
481:
482: DrawVertiLine(image, 0.0, p);
483: DrawVertiLine(image, 1.0, p);
484: DrawVertiLine(image, -1.0, p);
485: # endif
486: }
487:
488: /*******************************************************************************
489: +* Parte fija del cómputo.
490: *******************************************************************************/
491: static void IterComputationEspecial(png_colorpp image, int itermax, double modmax)
492: {
493: int row, col, iter;
494: double mod2;
495: double mod2max;
496: double zrtemp, zitemp;
497: double zr, zi;
498: double cr, ci;
499: int flag_changed = 0,
500: mandel_zone = 0,
501: is_break = 0;
502: # if 0
503: png_color p;
504: # endif
505:
506: for (row = 0; row < NUM_ROWS; row++)
507: {
508: for (col = 0; col < NUM_COLS; col++)
509: {
510:
511: cr = PixToCoordX(col);
512: ci = PixToCoordY(row);
513:
514: mod2max = modmax;
515:
516: zr = 0.0;
517: zi = 0.0;
518:
519: is_break = 0;
520: for (iter = 0; iter < itermax; iter++)
521: {
522: zrtemp = ComputeZR(zr, zi);
523: zitemp = ComputeZI(zr, zi);
524:
525: zr = zrtemp + cr;
526: zi = zitemp + ci;
527:
528: mod2 = zr*zr + zi*zi;
529: if (mod2 > mod2max)
530: {
531: if (mandel_zone)
532: {
533: mandel_zone = 0;
534: flag_changed = 1;
535: }
536: is_break = 1;
537: break;
538: }
539: }
540: if (is_break == 0)
541: {
542: if (mandel_zone == 0)
543: {
544: mandel_zone = 1;
545: flag_changed = 1;
546: }
547: }
548: else
549: {
550: if (mandel_zone == 1)
551: {
552: mandel_zone = 0;
553: flag_changed = 1;
554: }
555: }
556:
557: if (flag_changed)
558: {
559: # if 0
560: printf("%15.10lf %15.10lf\n", cr, ci);
561: # endif
562: flag_changed = 0;
563: }
564:
565: PNGColorAssign(&image[row][col], iter, itermax);
566: }
567: # if 0
568: printf("\n");
569: # endif
570: }
571:
572: # if 0
573: p.red = 0; p.green = 255; p.blue = 0;
574: DrawHorizLine(image, 0.0, p);
575: DrawHorizLine(image, 1.0, p);
576: DrawHorizLine(image, -1.0, p);
577:
578: DrawVertiLine(image, 0.0, p);
579: DrawVertiLine(image, 1.0, p);
580: DrawVertiLine(image, -1.0, p);
581: # endif
582: }
583:
584: /*******************************************************************************
585: +* GenFractal
586: +* Genera la imagen fractal para las zonas \Delta^+ y \Delta^-
587: *******************************************************************************/
588: int GenFractal(char *img_name, double alpha,
589: double beta,
590: int itermax,
591: double side_len,
592: double offset_x,
593: double offset_y)
594: {
595: png_colorpp image = NULL;
596: png_text info_text[NUM_TEXT];
597: int status;
598: double c_temp;
599:
600: /*******************************************************************************
601: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
602: *******************************************************************************/
603: SetSide(side_len);
604: SetOffsetX(offset_x);
605: SetOffsetY(offset_y);
606:
607: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
608: return ERROR;
609:
610: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
611:
612: /*******************************************************************************
613: +* Definición de la forma cuadrática.
614: +* Parte fija:
615: *******************************************************************************/
616: a1 = 0.0;
617: a2 = 1.0;
618: b2 = 0.0;
619:
620: /*******************************************************************************
621: +* Definición de la forma cuadrática.
622: +* Chequeo de condiciones sobre alpha y beta.
623: *******************************************************************************/
624: if (beta == 0.0) /* Beta ha de ser diferente de cero */
625: return ERROR;
626:
627: if ((alpha + 2.*beta) == 0.0) /* alpha + 2*beta != 0.0 */
628: return ERROR;
629:
630: /*******************************************************************************
631: +* Definición de la forma cuadrática.
632: +* Parte variable en función de alpha y beta:
633: *******************************************************************************/
634: c_temp = (4.*pow(alpha,3) - 27.*pow(beta,2))/pow(alpha + 2.*beta,3);
635:
636: if (c_temp < 0.0)
637: {
638: /* Zona F^-_{bc} */
639: c2 = 1.0;
640: zona = ZONA_Fbc_MENOS;
641: }
642: else
643: {
644: /* Zona F^+_{bc} */
645: c2 = -1.0;
646: zona = ZONA_Fbc_MAS;
647: }
648:
649: b1 = -c2*(alpha - beta)/(alpha + 2.*beta);
650: c1 = sqrt((-c2)*c_temp);
651:
652: if (zona == ZONA_Fbc_MAS)
653: {
654: if (c1 == 2.*b1 || c1 == -2.*b1)
655: {
656: fprintf(stderr, "#ERROR: Valores de b1 y c1 inválidos.\n");
657: return ERROR;
658: }
659: }
660:
661: /*******************************************************************************
662: +* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
663: *******************************************************************************/
664: minA = 1.;
665: if (zona == ZONA_Fbc_MAS)
666: {
667: if (b1 == 0.0 || c1 == 0.0)
668: ComputeMinAplus00();
669: else
670: ComputeMinAplus();
671: }
672: else if (zona == ZONA_Fbc_MENOS)
673: {
674: if (b1 == 0.0 || c1 == 0.0)
675: ComputeMinAminus00();
676: else
677: ComputeMinAminus();
678: }
679: else
680: {
681: fprintf(stderr, "#ERROR: Zona no implementada.\n");
682: return ERROR;
683: }
684:
685: /*******************************************************************************
686: +* Computación y generación de la imagen.
687: *******************************************************************************/
688: IterComputation(image, itermax);
689: status = WritePNG(img_name, image, info_text, NUM_TEXT);
690: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
691: return status;
692: }
693:
694: /*******************************************************************************
695: +* GenFractal
696: +* Genera la imagen fractal para las zonas C^+ y C^-
697: *******************************************************************************/
698: int GenFractalLinear(char *img_name, double alpha,
699: double beta,
700: int itermax,
701: double side_len,
702: double offset_x,
703: double offset_y)
704: {
705: png_colorpp image = NULL;
706: png_text info_text[NUM_TEXT];
707: int status;
708:
709: /*******************************************************************************
710: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
711: *******************************************************************************/
712: SetSide(side_len);
713: SetOffsetX(offset_x);
714: SetOffsetY(offset_y);
715:
716: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
717: return ERROR;
718:
719: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
720:
721: /*******************************************************************************
722: +* Definición de la forma cuadrática.
723: +* Parte fija:
724: *******************************************************************************/
725: a1 = 0.0;
726: a2 = 1.0;
727: b2 = 0.0;
728: c2 = 0.0;
729:
730: /*******************************************************************************
731: +* Definición de la forma cuadrática.
732: +* Chequeo de condiciones sobre beta.
733: *******************************************************************************/
734: if (beta == 0.0) /* Beta ha de ser diferente de cero */
735: return ERROR;
736:
737: if (alpha + 2.*beta != 0.0)
738: return ERROR; /* alpha + 2*beta ha de ser cero */
739:
740: /*******************************************************************************
741: +* Definición de la forma cuadrática.
742: +* Parte variable en función de beta: setting de zonas.
743: *******************************************************************************/
744: if (beta*(27.0+32.0*beta) < 0.0)
745: {
746: b1 = -1.0;
747: zona = ZONA_Fc_MENOS;
748: }
749: else
750: {
751: b1 = 1.0;
752: zona = ZONA_Fc_MAS;
753: }
754:
755: c1 = b1/9.0*sqrt(fabs(3.0*(27.0+32.0*beta)/beta));
756:
757: /*******************************************************************************
758: +* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
759: *******************************************************************************/
760: minA = 1.;
761: if (zona == ZONA_Fc_MAS)
762: {
763: if (c1 == 0.0)
764: ComputeMinAFcMas0();
765: else
766: ComputeMinAFcMas();
767: }
768: else if (zona == ZONA_Fc_MENOS)
769: {
770: if (c1 == 0.0)
771: ComputeMinAFcMenos0();
772: else
773: ComputeMinAFcMenos();
774: }
775: else
776: {
777: fprintf(stderr, "#ERROR: Zona no implementada.\n");
778: return ERROR;
779: }
780:
781: /*******************************************************************************
782: +* Computación y generación de la imagen.
783: *******************************************************************************/
784: IterComputation(image, itermax);
785: status = WritePNG(img_name, image, info_text, NUM_TEXT);
786: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
787: return status;
788: }
789:
790: /*******************************************************************************
791: +* GenFractal
792: +* Genera la imagen fractal para el eje X (menos el origen).
793: *******************************************************************************/
794: int GenFractalAlpha(char *img_name, double alpha,
795: double beta,
796: int itermax,
797: double side_len,
798: double offset_x,
799: double offset_y)
800: {
801: png_colorpp image = NULL;
802: png_text info_text[NUM_TEXT];
803: int status;
804:
805: /*******************************************************************************
806: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
807: *******************************************************************************/
808: SetSide(side_len);
809: SetOffsetX(offset_x);
810: SetOffsetY(offset_y);
811:
812: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
813: return ERROR;
814:
815: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
816:
817: /*******************************************************************************
818: +* Definición de la forma cuadrática.
819: +* Parte fija:
820: *******************************************************************************/
821: a1 = 1.0;
822: a2 = 0.0;
823: b1 = 1.0;
824: b2 = -1.0;
825: c2 = 0.0;
826:
827: /*******************************************************************************
828: +* Definición de la forma cuadrática.
829: +* Chequeo de condiciones sobre alpha y beta, y setting de zona.
830: *******************************************************************************/
831: if (alpha == 0.0 || beta != 0.0) /* Alpha ha de ser diferente de cero */
832: return ERROR; /* y beta igual a cero. */
833:
834: zona = ZONA_Gc;
835:
836: /*******************************************************************************
837: +* Definición de la forma cuadrática.
838: +* Parte variable en función de alpha:
839: *******************************************************************************/
840:
841: c1 = (4.0*alpha - 9.0)/alpha/12.0;
842:
843: /*******************************************************************************
844: +* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
845: *******************************************************************************/
846: ComputeMinAGc();
847: minA = 1.;
848:
849: # if 0
850: if (zona == ZONA_Gc)
851: {
852: fprintf(stderr, "#ERROR: Zona no implementada.\n");
853: return ERROR;
854: }
855: else
856: {
857: fprintf(stderr, "#ERROR: Zona no implementada.\n");
858: return ERROR;
859: }
860: # endif
861:
862: /*******************************************************************************
863: +* Computación y generación de la imagen.
864: *******************************************************************************/
865: # if 0
866: IterComputation(image, itermax);
867: # endif
868: IterComputationEspecial(image, itermax, 50.0);
869: status = WritePNG(img_name, image, info_text, NUM_TEXT);
870: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
871: return status;
872: }
873:
874: /*******************************************************************************
875: +* GenFractal_00
876: +* Genera la imagen fractal para el punto origen (0,0)
877: *******************************************************************************/
878: int GenFractal_00(char *img_name, double alpha,
879: double beta,
880: int itermax,
881: double side_len,
882: double offset_x,
883: double offset_y)
884: {
885: png_colorpp image = NULL;
886: png_text info_text[NUM_TEXT];
887: int status;
888:
889: /*******************************************************************************
890: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
891: *******************************************************************************/
892: SetSide(side_len);
893: SetOffsetX(offset_x);
894: SetOffsetY(offset_y);
895:
896: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
897: return ERROR;
898:
899: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
900:
901: /*******************************************************************************
902: +* Definición de la forma cuadrática.
903: *******************************************************************************/
904: a1 = 0.0;
905: b1 = 1.0;
906: c1 = 0.0;
907: a2 = 1.0;
908: b2 = 0.0;
909: c2 = -1.0;
910:
911: /*******************************************************************************
912: +* Chequeo de condiciones sobre alpha y beta. Setting de zona.
913: *******************************************************************************/
914: if (alpha != 0.0 || beta != 0.0) /* Alfa y Beta han de ser cero. */
915: return ERROR;
916:
917: zona = ZONA_00;
918:
919: /*******************************************************************************
920: +* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
921: *******************************************************************************/
922: minA = 1.;
923: if (zona == ZONA_00)
924: {
925: minA = 1.;
926: }
927: else
928: {
929: fprintf(stderr, "#ERROR: Zona no implementada.\n");
930: return ERROR;
931: }
932:
933: /*******************************************************************************
934: +* Computación y generación de la imagen.
935: *******************************************************************************/
936: IterComputation(image, itermax);
937: status = WritePNG(img_name, image, info_text, NUM_TEXT);
938: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
939: return status;
940: }
941:
942: /*******************************************************************************
943: +* GenFractalEspecial1
944: +* Genera la imagen para F^+_c cuando c = 0.
945: *******************************************************************************/
946: int GenFractalEspecial1(char *img_name, double alpha,
947: double beta,
948: int itermax,
949: double side_len,
950: double offset_x,
951: double offset_y)
952: {
953: png_colorpp image = NULL;
954: png_text info_text[NUM_TEXT];
955: int status;
956:
957: /*******************************************************************************
958: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
959: *******************************************************************************/
960: SetSide(side_len);
961: SetOffsetX(offset_x);
962: SetOffsetY(offset_y);
963:
964: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
965: return ERROR;
966:
967: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
968:
969: /*******************************************************************************
970: +* Definición de la forma cuadrática.
971: *******************************************************************************/
972: a1 = 0.0;
973: b1 = 1.0;
974: c1 = 0.0;
975: a2 = 1.0;
976: b2 = 0.0;
977: c2 = 0.0;
978:
979: IterComputationEspecial(image, itermax, 20.0);
980: status = WritePNG(img_name, image, info_text, NUM_TEXT);
981: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
982: return status;
983: }
984:
985: /*******************************************************************************
986: +* GenFractalEspecial2
987: +* Genera la imagen para F^-_c cuando c = 0.
988: *******************************************************************************/
989: int GenFractalEspecial2(char *img_name, double alpha,
990: double beta,
991: int itermax,
992: double side_len,
993: double offset_x,
994: double offset_y)
995: {
996: png_colorpp image = NULL;
997: png_text info_text[NUM_TEXT];
998: int status;
999:
1000: /*******************************************************************************
1001: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
1002: *******************************************************************************/
1003: SetSide(side_len);
1004: SetOffsetX(offset_x);
1005: SetOffsetY(offset_y);
1006:
1007: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
1008: return ERROR;
1009:
1010: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
1011:
1012: /*******************************************************************************
1013: +* Definición de la forma cuadrática.
1014: *******************************************************************************/
1015: a1 = 0.0;
1016: b1 = -1.0;
1017: c1 = 0.0;
1018: a2 = 1.0;
1019: b2 = 0.0;
1020: c2 = 0.0;
1021:
1022: IterComputationEspecial(image, itermax, 20.0);
1023: status = WritePNG(img_name, image, info_text, NUM_TEXT);
1024: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
1025: return status;
1026: }
1027:
1028: /*******************************************************************************
1029: +* GenFractalEspecial3
1030: +* Genera la imagen para G^_c cuando c = 0.
1031: *******************************************************************************/
1032: int GenFractalEspecial3(char *img_name, double alpha,
1033: double beta,
1034: int itermax,
1035: double side_len,
1036: double offset_x,
1037: double offset_y)
1038: {
1039: png_colorpp image = NULL;
1040: png_text info_text[NUM_TEXT];
1041: int status;
1042:
1043: /*******************************************************************************
1044: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
1045: *******************************************************************************/
1046: SetSide(side_len);
1047: SetOffsetX(offset_x);
1048: SetOffsetY(offset_y);
1049:
1050: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
1051: return ERROR;
1052:
1053: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
1054:
1055: /*******************************************************************************
1056: +* Definición de la forma cuadrática.
1057: *******************************************************************************/
1058: a1 = 1.0;
1059: b1 = 1.0;
1060: c1 = 0.0;
1061: a2 = 0.0;
1062: b2 = -1.0;
1063: c2 = 0.0;
1064:
1065: IterComputationEspecial(image, itermax, 20.0);
1066: status = WritePNG(img_name, image, info_text, NUM_TEXT);
1067: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
1068: return status;
1069: }
1070:
1071: /*******************************************************************************
1072: +* GenFractalEspecial5
1073: +* Genera el caso F^+_{00}
1074: *******************************************************************************/
1075: int GenFractalEspecial5(char *img_name, double alpha,
1076: double beta,
1077: int itermax,
1078: double side_len,
1079: double offset_x,
1080: double offset_y)
1081: {
1082: png_colorpp image = NULL;
1083: png_text info_text[NUM_TEXT];
1084: int status;
1085:
1086: /*******************************************************************************
1087: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
1088: *******************************************************************************/
1089: SetSide(side_len);
1090: SetOffsetX(offset_x);
1091: SetOffsetY(offset_y);
1092:
1093: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
1094: return ERROR;
1095:
1096: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
1097:
1098: /*******************************************************************************
1099: +* Definición de la forma cuadrática.
1100: *******************************************************************************/
1101: a1 = 0.0;
1102: b1 = 0.0;
1103: c1 = 0.0;
1104: a2 = 1.0;
1105: b2 = 0.0;
1106: c2 = -1.0;
1107:
1108: IterComputationEspecial(image, itermax, 40.0);
1109: status = WritePNG(img_name, image, info_text, NUM_TEXT);
1110: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
1111: return status;
1112: }
1113:
1114: /*******************************************************************************
1115: +* GenFractalEspecial6
1116: +* Genera el caso F^-_{00}
1117: *******************************************************************************/
1118: int GenFractalEspecial6(char *img_name, double alpha,
1119: double beta,
1120: int itermax,
1121: double side_len,
1122: double offset_x,
1123: double offset_y)
1124: {
1125: png_colorpp image = NULL;
1126: png_text info_text[NUM_TEXT];
1127: int status;
1128:
1129: /*******************************************************************************
1130: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
1131: *******************************************************************************/
1132: SetSide(side_len);
1133: SetOffsetX(offset_x);
1134: SetOffsetY(offset_y);
1135:
1136: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
1137: return ERROR;
1138:
1139: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
1140:
1141: /*******************************************************************************
1142: +* Definición de la forma cuadrática.
1143: *******************************************************************************/
1144: a1 = 0.0;
1145: b1 = 0.0;
1146: c1 = 0.0;
1147: a2 = 1.0;
1148: b2 = 0.0;
1149: c2 = 1.0;
1150:
1151: IterComputationEspecial(image, itermax, 40.0);
1152: status = WritePNG(img_name, image, info_text, NUM_TEXT);
1153: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
1154: return status;
1155: }
1156:
1157: /*******************************************************************************
1158: +* GenFractalEspecial7
1159: +* Genera el caso F^+_{bc} cuando $c=\pm 2b$
1160: *******************************************************************************/
1161: int GenFractalEspecial7(char *img_name, double alpha,
1162: double beta,
1163: int itermax,
1164: double side_len,
1165: double offset_x,
1166: double offset_y)
1167: {
1168: png_colorpp image = NULL;
1169: png_text info_text[NUM_TEXT];
1170: int status;
1171:
1172: /*******************************************************************************
1173: +* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
1174: *******************************************************************************/
1175: SetSide(side_len);
1176: SetOffsetX(offset_x);
1177: SetOffsetY(offset_y);
1178:
1179: if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
1180: return ERROR;
1181:
1182: BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);
1183:
1184: /*******************************************************************************
1185: +* Definición de la forma cuadrática.
1186: +* Parte fija:
1187: *******************************************************************************/
1188: a1 = 0.0;
1189: a2 = 1.0;
1190: b2 = 0.0;
1191: c2 = -1.0;
1192: b1 = beta;
1193: c1 = 2*beta;
1194:
1195: /*******************************************************************************
1196: +* Computación y generación de la imagen.
1197: *******************************************************************************/
1198: IterComputationEspecial(image, itermax, 40.0);
1199: status = WritePNG(img_name, image, info_text, NUM_TEXT);
1200: DeallocatePNG(image, NUM_ROWS, NUM_COLS);
1201: return status;
1202: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>