File:  [Repository ATC2] / QuadraticMandel / genfractal.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Oct 18 09:02:34 2011 UTC (12 years, 6 months ago) by cvsmgr
Branches: MAIN
CVS tags: HEAD
Quadratic fractal set generation.

/*******************************************************************************
+*  Fractal set generation for quadratic maps.
+*  Copyright (C) 2011, Raúl Durán Díaz, raul.duran@uah.es
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
/*******************************************************************************
+*
+* 9.12.2005
+*
+* $Id: genfractal.c,v 1.2 2011/10/18 09:02:34 cvsmgr Exp $
+* $Name:  $
+*
+* Falta por hacer el cálculo del mínimo A para Gc. Ahora se usa la
+* iteración especial con valor de 50.0
+*
*******************************************************************************/
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <math.h>
# include <stdarg.h>
# include "mypng.h"
# include "genfractal.h"
# include "mathutil.h"

enum Zona {ZONA_Fbc_MAS, ZONA_Fbc_MENOS, ZONA_Fc_MAS, ZONA_Fc_MENOS, ZONA_Gc, ZONA_00};

static double minA = 1.0;
static double a1   = 1.0;
static double b1   = 1.0;
static double c1   = 1.0;
static double a2   = 1.0;
static double b2   = 1.0;
static double c2   = 1.0;

enum Zona zona = ZONA_Fbc_MAS;

/*******************************************************************************
+* El siguiente if a 1 para imagen en color, 0 para blanco y negro.
*******************************************************************************/
# if 1
static void PNGColorAssign(png_colorp p, int iter, int itermax)
{
double ratio = 767.0*((double) iter / (double) itermax);
int    c     = lround(ratio);

# if 0
if (c != 0 && c != 767) printf("iter: %d, ratio=%lf, c=%d\n", iter, ratio, c);
# endif
   switch (c/256)
   {
      case 0:
        p->blue = c%256;
# if 0
if (c!=0 && c!=255) printf("Caso 0\n");
# endif
      break;

      case 1:
        p->blue  = 255 - c%256;
        p->green = c%256;
# if 0
if (c!=0 && c!=255) printf("Caso 1\n");
# endif
      break;

      default:
        p->green = 255 - c%256;
        p->red   = c%256;
# if 0
if (c!=0 && c!=255) printf("Caso default\n");
# endif
   }
}
# endif

/*******************************************************************************
+* El siguiente if a 0 para imagen en color, 1 para blanco y negro.
*******************************************************************************/
# if 0
static void PNGColorAssign(png_colorp p, int iter, int itermax)
{
double ratio = 255.0*((double) iter / (double) itermax);

/*******************************************************************************
+* El siguiente if a 1 para fondo blanco, fractal negro.
*******************************************************************************/
# if 1
   p->blue = p->green = p->red = 255 - lround(ratio);
# endif
/*******************************************************************************
+* El siguiente if a 1 para fondo negro, fractal blanco.
*******************************************************************************/
# if 0
   p->blue = p->green = p->red = lround(ratio);
# endif
}
# endif

static double ComputeZR(double zr, double zi)
{
   return a1*zr*zr + 2.0*b1*zr*zi + c1*zi*zi;
}

static double ComputeZI(double zr, double zi)
{
   return a2*zr*zr + 2.0*b2*zr*zi + c2*zi*zi;
}

static double maximo(double a, double b)
{
   if (a > b)
      return a;
   else
      return b;
}

static double minimo(double a, double b)
{
   if (a < b)
      return a;
   else
      return b;
}

/*******************************************************************************
+* Función A_t para la parte F^+_{bc}
*******************************************************************************/
static double Ap_t(double t)
{
   return pow(1. - pow(t,2),2)/pow(1. + pow(t,2),2) +
          pow(t,2)/pow(1. + pow(t,2),2)*
          (
           pow(c1,2)*pow(t,2)  +
           4.*pow(b1,2)        +
           4.*b1*c1*t
          );
}


static void ComputeMinAplus00(void)
{
double t = sqrt(2./(2.+pow(c1,2)));

   minA = minimo(minA, Ap_t(t));
   minA = minimo(minA, Ap_t(-t));

   return;
}

void ComputeMinAplus(void)
{
double k;
double p;
double q;
double d;
double rho;
double theta;
double l1q;
double l2q;
int    i;

   k = (pow(c1,2)-2.*pow(b1,2)+2.)/(3.*b1*c1);
   p = (-4.*k-3.*b1*c1-2.*pow(c1,2)*k+3.*b1*c1*pow(k,2)+4.*pow(b1,2)*k)/(b1*c1);
   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);

   if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
   {
      l1q = q*q/4.;
      l2q = -d/324.;
      rho = sqrt(l1q + l2q);
      theta = atan(sqrt(l2q/l1q));

      for (i = 0; i < 3; i++)
         minA = minimo(minA, Ap_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
   }
   else
   {
      fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
      minA = minimo(minA, Ap_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
   }

   return;
}

/*******************************************************************************
+* Función A_t para la parte F^-_{bc}
*******************************************************************************/
static double Am_t(double t)
{
   return 1 + pow(t,2)/pow(1. + pow(t,2),2)*
          (
           pow(c1,2)*pow(t,2)  +
           4.*pow(b1,2)        +
           4.*b1*c1*t
          );
}

static void ComputeMinAminus00(void)
{
   if (b1 != 0.0)
   {
      minA = minimo(minA, Am_t(1.));
      minA = minimo(minA, Am_t(-1.));
   }

   return;
}

static void ComputeMinAminus(void)
{
double k;
double p;
double q;
double d;
double rho;
double theta;
double l1q;
double l2q;
int    i;

   k = (pow(c1,2)-2.*pow(b1,2))/(3.*b1*c1);
   p = (4.*pow(b1,2)*k-2.*pow(c1,2)*k+3.*b1*c1*pow(k,2)-3.*b1*c1)/(b1*c1);
   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);

   if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
   {
      l1q = q*q/4.;
      l2q = -d/324.;
      rho = sqrt(l1q + l2q);
      theta = atan(sqrt(l2q/l1q));

      for (i = 0; i < 3; i++)
         minA = minimo(minA, Am_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
   }
   else
   {
      fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
      minA = minimo(minA, Am_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
   }

   return;
}

/*******************************************************************************
+* Función A_t y sus derivadas para la parte F^+_{c}
*******************************************************************************/
static double AFcMas_t(double t)
{
   return 1/pow(1. + pow(t,2),2)*
          (
           pow(c1,2)*pow(t,4)  +
           4.*c1*pow(t,3)      +
           4.*pow(t,2)         +
           1.
          );
}

static void ComputeMinAFcMas0(void)
{

   minA = minimo(minA, AFcMas_t(sqrt(2.)/.2));
   minA = minimo(minA, AFcMas_t(-sqrt(2.)/.2));

   return;
}

static void ComputeMinAFcMas(void)
{
double k;
double p;
double q;
double d;
double rho;
double theta;
double l1q;
double l2q;
int    i;

   k = 1./3.*(pow(c1,2)-2.)/c1;
   p = (-2.*k*pow(c1,2) + 4.*k + 3.*c1*pow(k,2) - 3.*c1)/c1;
   q = (-1. - pow(c1,2)*pow(k,2) + 2.*pow(k,2) + c1*pow(k,3) - 3.*c1*k)/c1;

   if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
   {
      l1q = q*q/4.;
      l2q = -d/324.;
      rho = sqrt(l1q + l2q);
      theta = atan(sqrt(l2q/l1q));

      for (i = 0; i < 3; i++)
         minA = minimo(minA, AFcMas_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
   }
   else
   {
      fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
      minA = minimo(minA, AFcMas_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
   }

   return;
}

/*******************************************************************************
+* Función A_t y sus derivadas para la parte F^-_{c}
*******************************************************************************/
static double AFcMenos_t(double t)
{
   return 1/pow(1. + pow(t,2),2)*
          (
           pow(c1,2)*pow(t,4)  -
           4.*c1*pow(t,3)      +
           4.*pow(t,2)         +
           1.
          );
}

static void ComputeMinAFcMenos0(void)
{

   minA = minimo(minA, AFcMenos_t(sqrt(2.)/.2));
   minA = minimo(minA, AFcMenos_t(-sqrt(2.)/.2));

   return;
}

static void ComputeMinAFcMenos(void)
{
double k;
double p;
double q;
double d;
double rho;
double theta;
double l1q;
double l2q;
int    i;

   k = -1./3.*(pow(c1,2)-2.)/c1;
   p = (2.*k*pow(c1,2) - 4.*k + 3.*c1*pow(k,2) - 3.*c1)/c1;
   q = (1. + pow(c1,2)*pow(k,2) - 2.*pow(k,2) + c1*pow(k,3) - 3.*c1*k)/c1;

   if ((d = 81.*pow(q,2)+12.*pow(p,3)) < 0.0)
   {
      l1q = q*q/4.;
      l2q = -d/324.;
      rho = sqrt(l1q + l2q);
      theta = atan(sqrt(l2q/l1q));

      for (i = 0; i < 3; i++)
         minA = minimo(minA, AFcMenos_t(2.*pow(rho, 1./3.)*cos(theta/3. + 2.*i*M_PI/3.) + k));
   }
   else
   {
      fprintf(stderr, "#WARNING: Discriminante positivo, sólo hay una solución.\n");
      minA = minimo(minA, AFcMenos_t(pow(-q/2. + sqrt(d)/18.,1./3.) + pow(-q/2. - sqrt(d)/18.,1./3.) + k));
   }

   return;
}

/*******************************************************************************
+* Función para la parte G_{c}
*******************************************************************************/
static void ComputeMinAGc(void)
{
double ypsilon;
double Ypsilon;
double tau1;

   ypsilon = 3*pow(c1,9)    - 9*pow(c1,8)    + 36*pow(c1,7)   -
             111*pow(c1,6)  + 540*pow(c1,5)  - 1107*pow(c1,4) +
             2592*pow(c1,3) - 3321*pow(c1,2) + 6237*c1-10044;

   if (ypsilon > 0.0)
   {
      Ypsilon = pow((c1-1.)*pow(c1+1.,2) + sqrt(ypsilon)/9., 1./3.);
      tau1 = (3*pow(Ypsilon,2) + 3*(1-c1)*Ypsilon -
             (pow(c1,3)-pow(c1,2)+3*c1-15))/(3*c1*Ypsilon);
   }
}

/*******************************************************************************
+* Cálculo del mínimo de la B y computación del Modúlo máximo.
*******************************************************************************/

static double ComputeMod2Max(double alpha, double beta)
{
double minB = 0.0;

   if (zona == ZONA_Fbc_MAS)
      minB = c1*alpha - sqrt(pow(2.*b1*alpha,2)+pow(2.*beta-c1*alpha,2));
   else if (zona == ZONA_Fbc_MENOS)
      minB = c1*alpha+2.*beta - sqrt(pow(2.*b1*alpha,2)+pow(c1*alpha,2));
   else if (zona == ZONA_Fc_MAS)
      minB = beta + alpha*c1 - sqrt(pow(beta-alpha*c1,2) + 4.*pow(alpha,2));
   else if (zona == ZONA_Fc_MENOS)
      minB = beta + alpha*c1 - sqrt(pow(beta-alpha*c1,2) + 4.*pow(alpha,2));
   else if (zona == ZONA_Gc)
      minB = alpha*(c1 + 1.) - sqrt(pow(-c1+1.,2)*pow(alpha,2)+4.*pow(alpha-beta,2));
   else if (zona == ZONA_00)
      minB = -2.*sqrt(pow(alpha,2) + pow(beta,2));
   else
   {
      fprintf(stderr, "#ERROR: Zona no implementada en el cálculo de min B.\n");
      return 0.;
   }

   return maximo(0., (1.-minB)/minA);
}

/*******************************************************************************
+* Parte fija del cómputo.
*******************************************************************************/
static void IterComputation(png_colorpp image, int itermax)
{
int         row, col, iter;
double      mod2;
double      mod2max;
double      zrtemp, zitemp;
double      zr, zi;
double      cr, ci;
# if 0
png_color   p;
# endif

   for (row = 0; row < NUM_ROWS; row++)
   {
      for (col = 0; col < NUM_COLS; col++)
      {
         cr = PixToCoordX(col);
         ci = PixToCoordY(row);

         mod2max = ComputeMod2Max(cr, ci);

         zr = 0.0;
         zi = 0.0;

         for (iter = 0; iter < itermax; iter++)
         {
            zrtemp = ComputeZR(zr, zi);
            zitemp = ComputeZI(zr, zi);

            zr = zrtemp + cr;
            zi = zitemp + ci;

            mod2 = zr*zr + zi*zi;
            if (mod2 > mod2max)
            {
# if 0
               printf("Nos salimos en la: %d\n", iter);
# endif
               break;
            }
         }
# if 0
         if (iter >= itermax)
            printf("Nos salimos por exceso, en (%lf, %lf)\n", cr, ci);
# endif

         PNGColorAssign(&image[row][col], iter, itermax);
      }
   }

# if 0
   p.red = 0; p.green = 255; p.blue = 0;
   DrawHorizLine(image, 0.0, p);
   DrawHorizLine(image, 1.0, p);
   DrawHorizLine(image, -1.0, p);

   DrawVertiLine(image, 0.0, p);
   DrawVertiLine(image, 1.0, p);
   DrawVertiLine(image, -1.0, p);
# endif
}

/*******************************************************************************
+* Parte fija del cómputo.
*******************************************************************************/
static void IterComputationEspecial(png_colorpp image, int itermax, double modmax)
{
int         row, col, iter;
double      mod2;
double      mod2max;
double      zrtemp, zitemp;
double      zr, zi;
double      cr, ci;
int         flag_changed = 0,
            mandel_zone  = 0,
            is_break     = 0;
# if 0
png_color   p;
# endif

   for (row = 0; row < NUM_ROWS; row++)
   {
      for (col = 0; col < NUM_COLS; col++)
      {

         cr = PixToCoordX(col);
         ci = PixToCoordY(row);

         mod2max = modmax;

         zr = 0.0;
         zi = 0.0;

         is_break = 0;
         for (iter = 0; iter < itermax; iter++)
         {
            zrtemp = ComputeZR(zr, zi);
            zitemp = ComputeZI(zr, zi);

            zr = zrtemp + cr;
            zi = zitemp + ci;

            mod2 = zr*zr + zi*zi;
            if (mod2 > mod2max)
            {
               if (mandel_zone)
               {
                  mandel_zone = 0;
                  flag_changed = 1;
               }
               is_break = 1;
               break;
            }
         }
         if (is_break == 0)
         {
            if (mandel_zone == 0)
            {
               mandel_zone = 1;
               flag_changed = 1;
            }
         }
         else
         {
            if (mandel_zone == 1)
            {
               mandel_zone = 0;
               flag_changed = 1;
            }
         }

         if (flag_changed)
         {
# if 0
            printf("%15.10lf %15.10lf\n", cr, ci);
# endif
            flag_changed = 0;
         }

         PNGColorAssign(&image[row][col], iter, itermax);
      }
# if 0
      printf("\n");
# endif
   }

# if 0
   p.red = 0; p.green = 255; p.blue = 0;
   DrawHorizLine(image, 0.0, p);
   DrawHorizLine(image, 1.0, p);
   DrawHorizLine(image, -1.0, p);

   DrawVertiLine(image, 0.0, p);
   DrawVertiLine(image, 1.0, p);
   DrawVertiLine(image, -1.0, p);
# endif
}

/*******************************************************************************
+* GenFractal
+* Genera la imagen fractal para las zonas \Delta^+ y \Delta^-
*******************************************************************************/
int GenFractal(char *img_name, double alpha,
                               double beta,
                               int    itermax,
                               double side_len,
                               double offset_x,
                               double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;
double      c_temp;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Parte fija:
*******************************************************************************/
   a1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Chequeo de condiciones sobre alpha y beta.
*******************************************************************************/
   if (beta == 0.0)   /* Beta ha de ser diferente de cero */
      return ERROR;

   if ((alpha + 2.*beta) == 0.0) /* alpha + 2*beta != 0.0 */
      return ERROR;

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Parte variable en función de alpha y beta:
*******************************************************************************/
   c_temp = (4.*pow(alpha,3) - 27.*pow(beta,2))/pow(alpha + 2.*beta,3);

   if (c_temp < 0.0)
   {
   /* Zona F^-_{bc} */
      c2 = 1.0;
      zona = ZONA_Fbc_MENOS;
   }
   else
   {
   /* Zona F^+_{bc} */
      c2 = -1.0;
      zona = ZONA_Fbc_MAS;
   }

   b1 = -c2*(alpha - beta)/(alpha + 2.*beta);
   c1 = sqrt((-c2)*c_temp);

   if (zona == ZONA_Fbc_MAS)
   {
      if (c1 == 2.*b1  ||  c1 == -2.*b1)
      {
         fprintf(stderr, "#ERROR: Valores de b1 y c1 inválidos.\n");
         return ERROR;
      }
   }

/*******************************************************************************
+* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
*******************************************************************************/
   minA = 1.;
   if (zona == ZONA_Fbc_MAS)
   {
      if (b1 == 0.0  ||  c1 == 0.0)
         ComputeMinAplus00();
      else
         ComputeMinAplus();
   }
   else if (zona == ZONA_Fbc_MENOS)
   {
      if (b1 == 0.0  ||  c1 == 0.0)
         ComputeMinAminus00();
      else
         ComputeMinAminus();
   }
   else
   {
      fprintf(stderr, "#ERROR: Zona no implementada.\n");
      return ERROR;
   }

/*******************************************************************************
+* Computación y generación de la imagen.
*******************************************************************************/
   IterComputation(image, itermax);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractal
+* Genera la imagen fractal para las zonas C^+ y C^-
*******************************************************************************/
int GenFractalLinear(char *img_name, double alpha,
                                     double beta,
                                     int    itermax,
                                     double side_len,
                                     double offset_x,
                                     double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Parte fija:
*******************************************************************************/
   a1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;
   c2 = 0.0;

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Chequeo de condiciones sobre beta.
*******************************************************************************/
   if (beta == 0.0)   /* Beta ha de ser diferente de cero */
      return ERROR;

   if (alpha + 2.*beta != 0.0)
      return ERROR;   /* alpha + 2*beta ha de ser cero */

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Parte variable en función de beta: setting de zonas.
*******************************************************************************/
   if (beta*(27.0+32.0*beta) < 0.0)
   {
      b1 = -1.0;
      zona = ZONA_Fc_MENOS;
   }
   else
   {
      b1 = 1.0;
      zona = ZONA_Fc_MAS;
   }

   c1 = b1/9.0*sqrt(fabs(3.0*(27.0+32.0*beta)/beta));

/*******************************************************************************
+* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
*******************************************************************************/
   minA = 1.;
   if (zona == ZONA_Fc_MAS)
   {
      if (c1 == 0.0)
         ComputeMinAFcMas0();
      else
         ComputeMinAFcMas();
   }
   else if (zona == ZONA_Fc_MENOS)
   {
      if (c1 == 0.0)
         ComputeMinAFcMenos0();
      else
         ComputeMinAFcMenos();
   }
   else
   {
      fprintf(stderr, "#ERROR: Zona no implementada.\n");
      return ERROR;
   }

/*******************************************************************************
+* Computación y generación de la imagen.
*******************************************************************************/
   IterComputation(image, itermax);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractal
+* Genera la imagen fractal para el eje X (menos el origen).
*******************************************************************************/
int GenFractalAlpha(char *img_name, double alpha,
                                    double beta,
                                    int    itermax,
                                    double side_len,
                                    double offset_x,
                                    double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Parte fija:
*******************************************************************************/
   a1 = 1.0;
   a2 = 0.0;
   b1 = 1.0;
   b2 = -1.0;
   c2 = 0.0;

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Chequeo de condiciones sobre alpha y beta, y setting de zona.
*******************************************************************************/
   if (alpha == 0.0  ||  beta != 0.0)   /* Alpha ha de ser diferente de cero */
      return ERROR;                     /* y beta igual a cero.              */

   zona = ZONA_Gc;

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Parte variable en función de alpha:
*******************************************************************************/

   c1 = (4.0*alpha - 9.0)/alpha/12.0;

/*******************************************************************************
+* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
*******************************************************************************/
   ComputeMinAGc();
   minA = 1.;

# if 0
   if (zona == ZONA_Gc)
   {
      fprintf(stderr, "#ERROR: Zona no implementada.\n");
      return ERROR;
   }
   else
   {
      fprintf(stderr, "#ERROR: Zona no implementada.\n");
      return ERROR;
   }
# endif

/*******************************************************************************
+* Computación y generación de la imagen.
*******************************************************************************/
# if 0
   IterComputation(image, itermax);
# endif
   IterComputationEspecial(image, itermax, 50.0);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractal_00
+* Genera la imagen fractal para el punto origen (0,0)
*******************************************************************************/
int GenFractal_00(char *img_name, double alpha,
                                  double beta,
                                  int    itermax,
                                  double side_len,
                                  double offset_x,
                                  double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
*******************************************************************************/
   a1 = 0.0;
   b1 = 1.0;
   c1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;
   c2 = -1.0;

/*******************************************************************************
+* Chequeo de condiciones sobre alpha y beta. Setting de zona.
*******************************************************************************/
   if (alpha != 0.0  ||  beta != 0.0)   /* Alfa y Beta han de ser cero. */
      return ERROR;

   zona = ZONA_00;

/*******************************************************************************
+* Cálculo del mínimo de A, según valores de b1, c1 y zonas.
*******************************************************************************/
   minA = 1.;
   if (zona == ZONA_00)
   {
      minA = 1.;
   }
   else
   {
      fprintf(stderr, "#ERROR: Zona no implementada.\n");
      return ERROR;
   }

/*******************************************************************************
+* Computación y generación de la imagen.
*******************************************************************************/
   IterComputation(image, itermax);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractalEspecial1
+* Genera la imagen para F^+_c cuando c = 0.
*******************************************************************************/
int GenFractalEspecial1(char *img_name, double alpha,
                                        double beta,
                                        int    itermax,
                                        double side_len,
                                        double offset_x,
                                        double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
*******************************************************************************/
   a1 = 0.0;
   b1 = 1.0;
   c1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;
   c2 = 0.0;

   IterComputationEspecial(image, itermax, 20.0);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractalEspecial2
+* Genera la imagen para F^-_c cuando c = 0.
*******************************************************************************/
int GenFractalEspecial2(char *img_name, double alpha,
                                        double beta,
                                        int    itermax,
                                        double side_len,
                                        double offset_x,
                                        double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
*******************************************************************************/
   a1 = 0.0;
   b1 = -1.0;
   c1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;
   c2 = 0.0;

   IterComputationEspecial(image, itermax, 20.0);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractalEspecial3
+* Genera la imagen para G^_c cuando c = 0.
*******************************************************************************/
int GenFractalEspecial3(char *img_name, double alpha,
                                        double beta,
                                        int    itermax,
                                        double side_len,
                                        double offset_x,
                                        double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
*******************************************************************************/
   a1 = 1.0;
   b1 = 1.0;
   c1 = 0.0;
   a2 = 0.0;
   b2 = -1.0;
   c2 = 0.0;

   IterComputationEspecial(image, itermax, 20.0);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractalEspecial5
+* Genera el caso F^+_{00}
*******************************************************************************/
int GenFractalEspecial5(char *img_name, double alpha,
                                        double beta,
                                        int    itermax,
                                        double side_len,
                                        double offset_x,
                                        double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
*******************************************************************************/
   a1 = 0.0;
   b1 = 0.0;
   c1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;
   c2 = -1.0;

   IterComputationEspecial(image, itermax, 40.0);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractalEspecial6
+* Genera el caso F^-_{00}
*******************************************************************************/
int GenFractalEspecial6(char *img_name, double alpha,
                                        double beta,
                                        int    itermax,
                                        double side_len,
                                        double offset_x,
                                        double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
*******************************************************************************/
   a1 = 0.0;
   b1 = 0.0;
   c1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;
   c2 = 1.0;

   IterComputationEspecial(image, itermax, 40.0);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

/*******************************************************************************
+* GenFractalEspecial7
+* Genera el caso F^+_{bc} cuando $c=\pm 2b$
*******************************************************************************/
int GenFractalEspecial7(char *img_name, double alpha,
                                        double beta,
                                        int    itermax,
                                        double side_len,
                                        double offset_x,
                                        double offset_y)
{
png_colorpp image = NULL;
png_text    info_text[NUM_TEXT];
int         status;

/*******************************************************************************
+* Parámetros de tamaño para la imagen. Reserva de memoria para ella.
*******************************************************************************/
   SetSide(side_len);
   SetOffsetX(offset_x);
   SetOffsetY(offset_y);

   if (!(image = AllocatePNG(NUM_ROWS, NUM_COLS)))
      return ERROR;

   BuildTextPtr(info_text, alpha, beta, itermax, side_len, offset_x, offset_y);

/*******************************************************************************
+* Definición de la forma cuadrática.
+* Parte fija:
*******************************************************************************/
   a1 = 0.0;
   a2 = 1.0;
   b2 = 0.0;
   c2 = -1.0;
   b1 = beta;
   c1 = 2*beta;

/*******************************************************************************
+* Computación y generación de la imagen.
*******************************************************************************/
   IterComputationEspecial(image, itermax, 40.0);
   status = WritePNG(img_name, image, info_text, NUM_TEXT);
   DeallocatePNG(image, NUM_ROWS, NUM_COLS);
   return status;
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>