diff options
| author | Lars-Dominik Braun <lars@6xq.net> | 2015-03-22 10:12:05 +0100 | 
|---|---|---|
| committer | Lars-Dominik Braun <lars@6xq.net> | 2015-05-02 21:36:45 +0200 | 
| commit | a093dd0ee969be5150fdff459db385fbc5613452 (patch) | |
| tree | 2809703489b70d94c7e8fd9deac967abe6ae2bcf | |
| parent | 539286a9a5b7663dfba7849328998601816b6f14 (diff) | |
| download | pucket-a093dd0ee969be5150fdff459db385fbc5613452.tar.gz pucket-a093dd0ee969be5150fdff459db385fbc5613452.tar.bz2 pucket-a093dd0ee969be5150fdff459db385fbc5613452.zip | |
Rewrite flam3_random
Disables flam3_mutate.
| -rw-r--r-- | flam3.c | 525 | ||||
| -rw-r--r-- | flam3.h | 16 | ||||
| -rw-r--r-- | genome.c | 299 | ||||
| -rw-r--r-- | genome.h | 25 | ||||
| -rw-r--r-- | main.c | 74 | ||||
| -rw-r--r-- | math.h | 15 | ||||
| -rw-r--r-- | parser.c | 4 | ||||
| -rw-r--r-- | parser.h | 2 | ||||
| -rw-r--r-- | wscript | 2 | 
9 files changed, 418 insertions, 544 deletions
| @@ -24,6 +24,7 @@  #include "parser.h"  #include "palettes.h"  #include "random.h" +#include "math.h"  #include <limits.h>  #include <locale.h>  #include <math.h> @@ -1025,24 +1026,21 @@ void clear_cp(flam3_genome *cp, int default_flag) {      cp->final_xform_index = -1;  } -flam3_genome *flam3_parse_xml2(char *xmldata, char *xmlfilename, int default_flag, int *ncps, randctx * const rc) { +flam3_genome *flam3_parse_xml2(const int fd, int default_flag, int *ncps, +		randctx * const rc) {     xmlDocPtr doc; /* Parsed XML document tree */     xmlNode *rootnode; -   char *bn;     int i;     int loc_all_ncps=0;     flam3_genome *loc_all_cp=NULL;     char* locale = NULL;     char* lorig  = setlocale(LC_NUMERIC, NULL); -   /* Parse XML string into internal document */ -   /* Forbid network access during read       */ -   doc = xmlReadMemory(xmldata, (int)strlen(xmldata), xmlfilename, NULL, XML_PARSE_NONET); - +   doc = xmlReadFd (fd, NULL, NULL, XML_PARSE_NONET);     /* Check for errors */     if (doc==NULL) { -      fprintf(stderr, "Failed to parse %s\n", xmlfilename); +      fprintf(stderr, "Failed to parse \n");        return NULL;     } @@ -1062,11 +1060,8 @@ flam3_genome *flam3_parse_xml2(char *xmldata, char *xmlfilename, int default_fla     if (setlocale(LC_NUMERIC, "C") == NULL)        fprintf(stderr, "error: couldn't set C locale\n"); -   /* Scan for <flame> nodes, starting with this node */ -   bn = basename(xmlfilename); -     /* Have to use &loc_all_cp since the memory gets allocated in scan_for_flame_nodes */ -   scan_for_flame_nodes(rootnode, bn, default_flag,&loc_all_cp,&loc_all_ncps, rc); +   scan_for_flame_nodes(rootnode, default_flag,&loc_all_cp,&loc_all_ncps, rc);     // restore locale     if (locale != NULL) { @@ -1126,46 +1121,6 @@ flam3_genome *flam3_parse_xml2(char *xmldata, char *xmlfilename, int default_fla     return loc_all_cp;  } -flam3_genome * flam3_parse_from_file(FILE *f, char *fname, int default_flag, int *ncps, randctx * const rc) { -   int i, c, slen = 5000; -   char *s, *snew; -   flam3_genome *ret; - -   /* Incrementally read XML file into a string */ -   s = malloc(slen); -   i = 0; -   do { -      c = getc(f); -      if (EOF == c) -         break; -      s[i++] = c; -      if (i == slen-1) { -         slen *= 2; -         snew = realloc(s, slen); -         if (snew==NULL) { -            fprintf(stderr,"XML file too large to be read. continuing with partial file.\n"); -            break; -         } else -            s = snew; -      } -   } while (1); - -   /* Null-terminate the read XML data */ -   s[i] = 0; - -   /* Parse the XML string */ -   if (fname) -      ret = flam3_parse_xml2(s, fname, default_flag, ncps, rc); -   else -      ret = flam3_parse_xml2(s, "stdin", default_flag, ncps, rc); -       -   free(s); -    -   return(ret); - -} - -  void flam3_apply_template(flam3_genome *cp, flam3_genome *templ) {     /* Check for invalid values - only replace those with valid ones */ @@ -2195,6 +2150,7 @@ void flam3_cross(flam3_genome *cp0, flam3_genome *cp1, flam3_genome *out, int cr  } +#if 0  void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, int sym, double speed, const palette_collection * const pc, randctx *rc) {     double randselect; @@ -2228,11 +2184,10 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in     if (mutate_mode == MUTATE_ALL_VARIATIONS) { -        do {           /* Create a random flame, and use the variations */           /* to replace those in the original              */ -         flam3_random(&mutation, ivars, ivars_n, sym, cp->num_xforms, pc, rc); +         flam3_random(&mutation, cp->num_xforms, pc, rc);           for (i = 0; i < cp->num_xforms; i++) {              for (j = 0; j < flam3_nvariations; j++) {                 if (cp->xform[i].var[j] != mutation.xform[i].var[j]) { @@ -2404,469 +2359,7 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in     clear_cp(&mutation,flam3_defaults_on);  } - -void flam3_random(flam3_genome *cp, int *ivars, int ivars_n, int sym, -			      int spec_xforms, const palette_collection * const pc, -				  randctx * const rc) { - -   int i, nxforms, var, samed, multid, samepost, postid, addfinal=0; -   int finum = -1; -   int n; -   int mvar = flam3_nvariations; -   double sum; - -   static int xform_distrib[] = { -     2, 2, 2, 2, -     3, 3, 3, 3, -     4, 4, 4, -     5, 5, -     6 -   }; - -   clear_cp(cp,flam3_defaults_on); - -   cp->hue_rotation = rand_mod(rc, 8) ? 0.0 : rand_d01(rc); -   const palette * const p = palette_random (pc, rc); -   assert (p != NULL); -   palette_copy (p, &cp->palette); -   palette_rotate_hue (&cp->palette, cp->hue_rotation); -   cp->time = 0.0; -   cp->interpolation = flam3_interpolation_linear; -   cp->palette_interpolation = flam3_palette_interpolation_hsv; - -   /* Choose the number of xforms */ -   if (spec_xforms>0) { -      nxforms = spec_xforms; -      flam3_add_xforms(cp,nxforms,0,0); -   } else { -      nxforms = rand_distrib(rc, xform_distrib); -      flam3_add_xforms(cp,nxforms,0,0); -      /* Add a final xform 15% of the time */ -      addfinal = rand_d01(rc) < 0.15; -      if (addfinal) { -         flam3_add_xforms(cp,1,0,1); -         nxforms = nxforms + addfinal; -         finum = nxforms-1; -      } -   }    - -   /* If first input variation is 'flam3_variation_random' */ -   /* choose one to use or decide to use multiple    */ -   if (flam3_variation_random == ivars[0]) { -      if (rand_bool(rc)) { -         var = rand_mod(rc, mvar); -      } else { -         var = flam3_variation_random; -      } -   } else { -      var = flam3_variation_random_fromspecified; -   } - -   samed = rand_bool(rc); -   multid = rand_bool(rc); -   postid = rand_d01(rc) < 0.6; -   samepost = rand_bool(rc); - -   /* Loop over xforms */ -   for (i = 0; i < nxforms; i++) { -      int j, k; -      cp->xform[i].density = 1.0 / nxforms; -      cp->xform[i].color = i&1; -      cp->xform[i].color_speed = 0.5; -      cp->xform[i].animate = 1.0; -      for (j = 0; j < 3; j++) { -         for (k = 0; k < 2; k++) { -            cp->xform[i].c[j][k] = rand_d11(rc); -            cp->xform[i].post[j][k] = (double)(k==j); -         } -      } -       -      if ( i != finum ) { -       -         if (!postid) { - -            for (j = 0; j < 3; j++) -            for (k = 0; k < 2; k++) { -               if (samepost || (i==0)) -                  cp->xform[i].post[j][k] = rand_d11(rc); -               else -                  cp->xform[i].post[j][k] = cp->xform[0].post[j][k]; -            } -         } - -         /* Clear all variation coefs */ -         for (j = 0; j < flam3_nvariations; j++) -            cp->xform[i].var[j] = 0.0; - -         if (flam3_variation_random != var &&  -               flam3_variation_random_fromspecified != var) { - -            /* Use only one variation specified for all xforms */ -            cp->xform[i].var[var] = 1.0; - -         } else if (multid && flam3_variation_random == var) { - -           /* Choose a random var for this xform */ -             cp->xform[i].var[rand_mod(rc, mvar)] = 1.0; - -         } else { - -            if (samed && i > 0) { - -               /* Copy the same variations from the previous xform */ -               for (j = 0; j < flam3_nvariations; j++) { -                  cp->xform[i].var[j] = cp->xform[i-1].var[j]; -                  flam3_copy_params(&(cp->xform[i]),&(cp->xform[i-1]),j); -               } - -            } else { - -               /* Choose a random number of vars to use, at least 2 */ -               /* but less than flam3_nvariations.Probability leans */ -               /* towards fewer variations.                         */ -               n = 2; -               while ((rand_bool(rc)) && (n<mvar)) -                  n++; -                -               /* Randomly choose n variations, and change their weights. */ -               /* A var can be selected more than once, further reducing  */ -               /* the probability that multiple vars are used.            */ -               for (j = 0; j < n; j++) { -                  if (flam3_variation_random_fromspecified != var) -                     cp->xform[i].var[rand_mod(rc, mvar)] = rand_d01(rc); -                  else -                     cp->xform[i].var[ivars[rand_mod(rc, ivars_n)]] = rand_d01(rc); -               } - -               /* Normalize weights to 1.0 total. */ -               sum = 0.0; -               for (j = 0; j < flam3_nvariations; j++) -                  sum += cp->xform[i].var[j]; -               if (sum == 0.0) -                  cp->xform[i].var[rand_mod(rc, flam3_nvariations)] = 1.0; -               else { -                  for (j = 0; j < flam3_nvariations; j++) -                     cp->xform[i].var[j] /= sum; -               } -            } -         } -      } else { -         /* Handle final xform randomness. */ -         n = 1; -         if (rand_bool(rc)) n++; -          -         /* Randomly choose n variations, and change their weights. */ -         /* A var can be selected more than once, further reducing  */ -         /* the probability that multiple vars are used.            */ -         for (j = 0; j < n; j++) { -            if (flam3_variation_random_fromspecified != var) -               cp->xform[i].var[rand_mod(rc, mvar)] = rand_d01(rc); -            else -               cp->xform[i].var[ivars[rand_mod(rc, ivars_n)]] = rand_d01(rc); -         } - -         /* Normalize weights to 1.0 total. */ -         sum = 0.0; -         for (j = 0; j < flam3_nvariations; j++) -            sum += cp->xform[i].var[j]; -         if (sum == 0.0) -            cp->xform[i].var[rand_mod(rc, flam3_nvariations)] = 1.0; -         else { -            for (j = 0; j < flam3_nvariations; j++) -               cp->xform[i].var[j] /= sum; -         } -      }   - -      /* Generate random params for parametric variations, if selected. */ -      if (cp->xform[i].var[VAR_BLOB] > 0) { -         /* Create random params for blob */ -         cp->xform[i].blob_low = 0.2 + 0.5 * rand_d01(rc); -         cp->xform[i].blob_high = 0.8 + 0.4 * rand_d01(rc); -         cp->xform[i].blob_waves = (int)(2 + 5 * rand_d01(rc)); -      } - -      if (cp->xform[i].var[VAR_PDJ] > 0) { -         /* Create random params for PDJ */ -         cp->xform[i].pdj_a = 3.0 * rand_d11(rc); -         cp->xform[i].pdj_b = 3.0 * rand_d11(rc); -         cp->xform[i].pdj_c = 3.0 * rand_d11(rc); -         cp->xform[i].pdj_d = 3.0 * rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_FAN2] > 0) { -         /* Create random params for fan2 */ -         cp->xform[i].fan2_x = rand_d11(rc); -         cp->xform[i].fan2_y = rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_RINGS2] > 0) { -         /* Create random params for rings2 */ -         cp->xform[i].rings2_val = 2*rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_PERSPECTIVE] > 0) { - -         /* Create random params for perspective */ -         cp->xform[i].perspective_angle = rand_d01(rc); -         cp->xform[i].perspective_dist = 2*rand_d01(rc) + 1.0; - -      } - -      if (cp->xform[i].var[VAR_JULIAN] > 0) { - -         /* Create random params for julian */ -         cp->xform[i].julian_power = (int)(5*rand_d01(rc) + 2); -         cp->xform[i].julian_dist = 1.0; - -      } - -      if (cp->xform[i].var[VAR_JULIASCOPE] > 0) { - -         /* Create random params for juliaScope */ -         cp->xform[i].juliascope_power = (int)(5*rand_d01(rc) + 2); -         cp->xform[i].juliascope_dist = 1.0; - -      } - -      if (cp->xform[i].var[VAR_RADIAL_BLUR] > 0) { - -         /* Create random params for radialBlur */ -         cp->xform[i].radial_blur_angle = (2 * rand_d01(rc) - 1); - -      } - -      if (cp->xform[i].var[VAR_PIE] > 0) { -         /* Create random params for pie */ -         cp->xform[i].pie_slices = (int) 10.0*rand_d01(rc); -         cp->xform[i].pie_thickness = rand_d01(rc); -         cp->xform[i].pie_rotation = 2.0 * M_PI * rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_NGON] > 0) { -         /* Create random params for ngon */ -         cp->xform[i].ngon_sides = (int) rand_d01(rc)* 10 + 3; -         cp->xform[i].ngon_power = 3*rand_d01(rc) + 1; -         cp->xform[i].ngon_circle = 3*rand_d01(rc); -         cp->xform[i].ngon_corners = 2*rand_d01(rc)*cp->xform[i].ngon_circle; -      } - -      if (cp->xform[i].var[VAR_CURL] > 0) { -         /* Create random params for curl */ -         cp->xform[i].curl_c1 = rand_d01(rc); -         cp->xform[i].curl_c2 = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_RECTANGLES] > 0) { -         /* Create random params for rectangles */ -         cp->xform[i].rectangles_x = rand_d01(rc); -         cp->xform[i].rectangles_y = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_DISC2] > 0) { -      /* Create random params for disc2 */ -      cp->xform[i].disc2_rot = 0.5 * rand_d01(rc); -      cp->xform[i].disc2_twist = 0.5 * rand_d01(rc); - -      } - -      if (cp->xform[i].var[VAR_SUPER_SHAPE] > 0) { -         /* Create random params for supershape */ -         cp->xform[i].super_shape_rnd = rand_d01(rc); -         cp->xform[i].super_shape_m = (int) rand_d01(rc)*6; -         cp->xform[i].super_shape_n1 = rand_d01(rc)*40; -         cp->xform[i].super_shape_n2 = rand_d01(rc)*20; -         cp->xform[i].super_shape_n3 = cp->xform[i].super_shape_n2; -         cp->xform[i].super_shape_holes = 0.0; -      } - -      if (cp->xform[i].var[VAR_FLOWER] > 0) { -         /* Create random params for flower */ -         cp->xform[i].flower_petals = 4 * rand_d01(rc); -         cp->xform[i].flower_holes = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_CONIC] > 0) { -         /* Create random params for conic */ -         cp->xform[i].conic_eccentricity = rand_d01(rc); -         cp->xform[i].conic_holes = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_PARABOLA] > 0) { -         /* Create random params for parabola */ -         cp->xform[i].parabola_height = 0.5 + rand_d01(rc); -         cp->xform[i].parabola_width = 0.5 + rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_BENT2] > 0) { -         /* Create random params for bent2 */ -         cp->xform[i].bent2_x = 3*(-0.5 + rand_d01(rc)); -         cp->xform[i].bent2_y = 3*(-0.5 + rand_d01(rc)); -      } - -      if (cp->xform[i].var[VAR_BIPOLAR] > 0) { -         /* Create random params for bipolar */ -         cp->xform[i].bipolar_shift = 2.0 * rand_d01(rc) - 1; -      } - -      if (cp->xform[i].var[VAR_CELL] > 0) { -         /* Create random params for cell */ -         cp->xform[i].cell_size = 2.0 * rand_d01(rc) + 0.5; -      } - -      if (cp->xform[i].var[VAR_CPOW] > 0) { -         /* Create random params for cpow */ -         cp->xform[i].cpow_r = 3.0 * rand_d01(rc); -         cp->xform[i].cpow_i = rand_d01(rc) - 0.5; -         cp->xform[i].cpow_power = (int)(5.0 * rand_d01(rc)); -      } - -      if (cp->xform[i].var[VAR_CURVE] > 0) { -         /* Create random params for curve */ -         cp->xform[i].curve_xamp = 5 * (rand_d01(rc)-.5); -         cp->xform[i].curve_yamp = 4 * (rand_d01(rc)-.5); -         cp->xform[i].curve_xlength = 2 * (rand_d01(rc)+.5); -         cp->xform[i].curve_ylength = 2 * (rand_d01(rc)+.5); -      } - -      if (cp->xform[i].var[VAR_ESCHER] > 0) { -         /* Create random params for escher */ -         cp->xform[i].escher_beta = M_PI * rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_LAZYSUSAN] > 0) { -         /* Create random params for lazysusan */ -         cp->xform[i].lazysusan_x = 2.0*rand_d11(rc); -         cp->xform[i].lazysusan_y = 2.0*rand_d11(rc); -         cp->xform[i].lazysusan_spin = M_PI*rand_d11(rc); -         cp->xform[i].lazysusan_space = 2.0*rand_d11(rc); -         cp->xform[i].lazysusan_twist = 2.0*rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_MODULUS] > 0) { -         /* Create random params for modulus */ -         cp->xform[i].modulus_x = rand_d11(rc); -         cp->xform[i].modulus_y = rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_OSCILLOSCOPE] > 0) { -         /* Create random params for oscope */ -         cp->xform[i].oscope_separation = 1.0 + rand_d11(rc); -         cp->xform[i].oscope_frequency = M_PI * rand_d11(rc); -         cp->xform[i].oscope_amplitude = 1.0 + 2 * rand_d01(rc); -         cp->xform[i].oscope_damping = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_POPCORN2] > 0) { -         /* Create random params for popcorn2 */ -         cp->xform[i].popcorn2_x = 0.2 * rand_d01(rc); -         cp->xform[i].popcorn2_y = 0.2 * rand_d01(rc); -         cp->xform[i].popcorn2_c = 5 * rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_SEPARATION] > 0) { -         /* Create random params for separation */ -         cp->xform[i].separation_x = 1 + rand_d11(rc); -         cp->xform[i].separation_y = 1 + rand_d11(rc); -         cp->xform[i].separation_xinside = rand_d11(rc); -         cp->xform[i].separation_yinside = rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_SPLIT] > 0) { -         /* Create random params for split */ -         cp->xform[i].split_xsize = rand_d11(rc); -         cp->xform[i].split_ysize = rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_SPLITS] > 0) { -         /* Create random params for splits */ -         cp->xform[i].splits_x = rand_d11(rc); -         cp->xform[i].splits_y = rand_d11(rc); -      } - -      if (cp->xform[i].var[VAR_STRIPES] > 0) { -         /* Create random params for stripes */ -         cp->xform[i].stripes_space = rand_d01(rc); -         cp->xform[i].stripes_warp = 5*rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_WEDGE] > 0) { -         /* Create random params for wedge */ -         cp->xform[i].wedge_angle = M_PI*rand_d01(rc); -         cp->xform[i].wedge_hole = 0.5*rand_d11(rc); -         cp->xform[i].wedge_count = floor(5*rand_d01(rc))+1; -         cp->xform[i].wedge_swirl = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_WEDGE_JULIA] > 0) { - -         /* Create random params for wedge_julia */ -         cp->xform[i].wedge_julia_power = (int)(5*rand_d01(rc) + 2); -         cp->xform[i].wedge_julia_dist = 1.0; -         cp->xform[i].wedge_julia_count = (int)(3*rand_d01(rc) + 1); -         cp->xform[i].wedge_julia_angle = M_PI * rand_d01(rc); - -      } - -      if (cp->xform[i].var[VAR_WEDGE_SPH] > 0) { -         /* Create random params for wedge_sph */ -         cp->xform[i].wedge_sph_angle = M_PI*rand_d01(rc); -         cp->xform[i].wedge_sph_hole = 0.5*rand_d11(rc); -         cp->xform[i].wedge_sph_count = floor(5*rand_d01(rc))+1; -         cp->xform[i].wedge_sph_swirl = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_WHORL] > 0) { -         /* Create random params for whorl */ -         cp->xform[i].whorl_inside = rand_d01(rc); -         cp->xform[i].whorl_outside = rand_d01(rc); -      } - -      if (cp->xform[i].var[VAR_WAVES2] > 0) { -         /* Create random params for waves2 */ -         cp->xform[i].waves2_scalex = 0.5 + rand_d01(rc); -         cp->xform[i].waves2_scaley = 0.5 + rand_d01(rc); -         cp->xform[i].waves2_freqx = 4 * rand_d01(rc); -         cp->xform[i].waves2_freqy = 4 * rand_d01(rc); -      }          - -      if (cp->xform[i].var[VAR_AUGER] > 0) { -         /* Create random params for auger */ -         cp->xform[i].auger_sym = 0; -         cp->xform[i].auger_weight = 0.5 + rand_d01(rc)/2.0; -         cp->xform[i].auger_freq = floor(5*rand_d01(rc))+1; -         cp->xform[i].auger_scale = rand_d01(rc); -      }          - -      if (cp->xform[i].var[VAR_FLUX] > 0) { -         /* Create random params for flux */ -         cp->xform[i].flux_spread = 0.5 + rand_d01(rc)/2.0; -      } - -      if (cp->xform[i].var[VAR_MOBIUS] > 0) { -         /* Create random params for mobius */ -         cp->xform[i].mobius_re_a = rand_d11(rc); -         cp->xform[i].mobius_im_a = rand_d11(rc); -         cp->xform[i].mobius_re_b = rand_d11(rc); -         cp->xform[i].mobius_im_b = rand_d11(rc); -         cp->xform[i].mobius_re_c = rand_d11(rc); -         cp->xform[i].mobius_im_c = rand_d11(rc); -         cp->xform[i].mobius_re_d = rand_d11(rc); -         cp->xform[i].mobius_im_d = rand_d11(rc); -      } - -   } - -   /* Randomly add symmetry (but not if we've already added a final xform) */ -   if (sym || (!rand_mod(rc, 4) && !addfinal)) -      flam3_add_symmetry(cp, sym, rc); -   else -      cp->symmetry = 0; - -   //qsort((char *) cp->xform, (cp->num_xforms-addfinal), sizeof(flam3_xform), compare_xforms); - - -} - +#endif  static int sort_by_x(const void *av, const void *bv) {      double4 a = *((double4 *) av); @@ -34,13 +34,9 @@  #include "random.h" -#define flam3_variation_random (-1) -#define flam3_variation_random_fromspecified (-2) -  extern char *flam3_variation_names[];  #define flam3_nvariations 99 -#define flam3_nxforms     12  #define flam3_interpolation_linear 0  #define flam3_interpolation_smooth 1 @@ -511,13 +507,8 @@ void flam3_print(FILE *f, flam3_genome *g, char *extra_attributes);  void flam3_print_xform(FILE *f, flam3_xform *x, int final_flag, int numstd, double *chaos_row, int motion_flag);  char *flam3_print_to_string(flam3_genome *cp); -/* ivars is a list of variations to use, or flam3_variation_random     */ -/* ivars_n is the number of values in ivars to select from.            */ -/* sym is either a symmetry group or 0 meaning random or no symmetry   */ -/* spec_xforms specifies the number of xforms to use, setting to 0 makes the number random. */ -void flam3_random(flam3_genome *cp, int *ivars, int ivars_n, int sym, -			      int spec_xforms, const palette_collection * const pc, -				  randctx * const rc); +void flam3_random(flam3_genome *cp, const unsigned int max_xform, +		const palette_collection * const pc, randctx * const rc);  void add_to_action(char *action, char *addtoaction); @@ -525,8 +516,7 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in  void flam3_cross(flam3_genome *cp0, flam3_genome *cp1, flam3_genome *out, int cross_mode, randctx *rc);  /* return NULL in case of error */ -flam3_genome *flam3_parse_xml2(char *s, char *fn, int default_flag, int *ncps, randctx * const); -flam3_genome *flam3_parse_from_file(FILE *f, char *fn, int default_flag, int *ncps, randctx * const); +flam3_genome *flam3_parse_xml2(const int, int default_flag, int *ncps, randctx * const);  void flam3_add_symmetry(flam3_genome *cp, int sym, randctx * const rc); diff --git a/genome.c b/genome.c new file mode 100644 index 0000000..547a6a8 --- /dev/null +++ b/genome.c @@ -0,0 +1,299 @@ +/* +    Copyright (C) 1992-2009 Spotworks LLC +	              2015 pucket contributors + +    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/>. +*/ + +#include <math.h> +#include <string.h> + +#include "genome.h" +#include "math.h" +#include "flam3.h" +#include "random.h" + +/* Generate random params for parametric variations */ +static void random_xform_param (flam3_xform * const xform, const unsigned int i, +		randctx * const rc) { +	switch (i) { +		case VAR_BLOB: +			xform->blob_low = 0.2 + 0.5 * rand_d01(rc); +			xform->blob_high = 0.8 + 0.4 * rand_d01(rc); +			xform->blob_waves = (int)(2 + 5 * rand_d01(rc)); +			break; + +		case VAR_PDJ: +			xform->pdj_a = 3.0 * rand_d11(rc); +			xform->pdj_b = 3.0 * rand_d11(rc); +			xform->pdj_c = 3.0 * rand_d11(rc); +			xform->pdj_d = 3.0 * rand_d11(rc); +			break; + +		case VAR_FAN2: +			xform->fan2_x = rand_d11(rc); +			xform->fan2_y = rand_d11(rc); +			break; + +		case VAR_RINGS2: +			xform->rings2_val = 2*rand_d01(rc); +			break; + +		case VAR_PERSPECTIVE: +			xform->perspective_angle = rand_d01(rc); +			xform->perspective_dist = 2*rand_d01(rc) + 1.0; +			break; + +		case VAR_JULIAN: +			xform->julian_power = (int)(5*rand_d01(rc) + 2); +			xform->julian_dist = 1.0; +			break; + +		case VAR_JULIASCOPE: +			xform->juliascope_power = (int)(5*rand_d01(rc) + 2); +			xform->juliascope_dist = 1.0; +			break; + +		case VAR_RADIAL_BLUR: +			xform->radial_blur_angle = (2 * rand_d01(rc) - 1); +			break; + +		case VAR_PIE: +			xform->pie_slices = (int) 10.0*rand_d01(rc); +			xform->pie_thickness = rand_d01(rc); +			xform->pie_rotation = 2.0 * M_PI * rand_d11(rc); +			break; + +		case VAR_NGON: +			xform->ngon_sides = (int) rand_d01(rc)* 10 + 3; +			xform->ngon_power = 3*rand_d01(rc) + 1; +			xform->ngon_circle = 3*rand_d01(rc); +			xform->ngon_corners = 2*rand_d01(rc)*xform->ngon_circle; +			break; + +		case VAR_CURL: +			xform->curl_c1 = rand_d01(rc); +			xform->curl_c2 = rand_d01(rc); +			break; + +		case VAR_RECTANGLES: +			xform->rectangles_x = rand_d01(rc); +			xform->rectangles_y = rand_d01(rc); +			break; + +		case VAR_DISC2: +			xform->disc2_rot = 0.5 * rand_d01(rc); +			xform->disc2_twist = 0.5 * rand_d01(rc); +			break; + +		case VAR_SUPER_SHAPE: +			xform->super_shape_rnd = rand_d01(rc); +			xform->super_shape_m = (int) rand_d01(rc)*6; +			xform->super_shape_n1 = rand_d01(rc)*40; +			xform->super_shape_n2 = rand_d01(rc)*20; +			xform->super_shape_n3 = xform->super_shape_n2; +			xform->super_shape_holes = 0.0; +			break; + +		case VAR_FLOWER: +			xform->flower_petals = 4 * rand_d01(rc); +			xform->flower_holes = rand_d01(rc); +			break; + +		case VAR_CONIC: +			xform->conic_eccentricity = rand_d01(rc); +			xform->conic_holes = rand_d01(rc); +			break; + +		case VAR_PARABOLA: +			xform->parabola_height = 0.5 + rand_d01(rc); +			xform->parabola_width = 0.5 + rand_d01(rc); +			break; + +		case VAR_BENT2: +			xform->bent2_x = 3*(-0.5 + rand_d01(rc)); +			xform->bent2_y = 3*(-0.5 + rand_d01(rc)); +			break; + +		case VAR_BIPOLAR: +			xform->bipolar_shift = 2.0 * rand_d01(rc) - 1; +			break; + +		case VAR_CELL: +			xform->cell_size = 2.0 * rand_d01(rc) + 0.5; +			break; + +		case VAR_CPOW: +			xform->cpow_r = 3.0 * rand_d01(rc); +			xform->cpow_i = rand_d01(rc) - 0.5; +			xform->cpow_power = (int)(5.0 * rand_d01(rc)); +			break; + +		case VAR_CURVE: +			xform->curve_xamp = 5 * (rand_d01(rc)-.5); +			xform->curve_yamp = 4 * (rand_d01(rc)-.5); +			xform->curve_xlength = 2 * (rand_d01(rc)+.5); +			xform->curve_ylength = 2 * (rand_d01(rc)+.5); +			break; + +		case VAR_ESCHER: +			xform->escher_beta = M_PI * rand_d11(rc); +			break; + +		case VAR_LAZYSUSAN: +			xform->lazysusan_x = 2.0*rand_d11(rc); +			xform->lazysusan_y = 2.0*rand_d11(rc); +			xform->lazysusan_spin = M_PI*rand_d11(rc); +			xform->lazysusan_space = 2.0*rand_d11(rc); +			xform->lazysusan_twist = 2.0*rand_d11(rc); +			break; + +		case VAR_MODULUS: +			xform->modulus_x = rand_d11(rc); +			xform->modulus_y = rand_d11(rc); +			break; + +		case VAR_OSCILLOSCOPE: +			xform->oscope_separation = 1.0 + rand_d11(rc); +			xform->oscope_frequency = M_PI * rand_d11(rc); +			xform->oscope_amplitude = 1.0 + 2 * rand_d01(rc); +			xform->oscope_damping = rand_d01(rc); +			break; + +		case VAR_POPCORN2: +			xform->popcorn2_x = 0.2 * rand_d01(rc); +			xform->popcorn2_y = 0.2 * rand_d01(rc); +			xform->popcorn2_c = 5 * rand_d01(rc); +			break; + +		case VAR_SEPARATION: +			xform->separation_x = 1 + rand_d11(rc); +			xform->separation_y = 1 + rand_d11(rc); +			xform->separation_xinside = rand_d11(rc); +			xform->separation_yinside = rand_d11(rc); +			break; + +		case VAR_SPLIT: +			xform->split_xsize = rand_d11(rc); +			xform->split_ysize = rand_d11(rc); +			break; + +		case VAR_SPLITS: +			xform->splits_x = rand_d11(rc); +			xform->splits_y = rand_d11(rc); +			break; + +		case VAR_STRIPES: +			xform->stripes_space = rand_d01(rc); +			xform->stripes_warp = 5*rand_d01(rc); +			break; + +		case VAR_WEDGE: +			xform->wedge_angle = M_PI*rand_d01(rc); +			xform->wedge_hole = 0.5*rand_d11(rc); +			xform->wedge_count = floor(5*rand_d01(rc))+1; +			xform->wedge_swirl = rand_d01(rc); +			break; + +		case VAR_WEDGE_JULIA: +			xform->wedge_julia_power = (int)(5*rand_d01(rc) + 2); +			xform->wedge_julia_dist = 1.0; +			xform->wedge_julia_count = (int)(3*rand_d01(rc) + 1); +			xform->wedge_julia_angle = M_PI * rand_d01(rc); +			break; + +		case VAR_WEDGE_SPH: +			xform->wedge_sph_angle = M_PI*rand_d01(rc); +			xform->wedge_sph_hole = 0.5*rand_d11(rc); +			xform->wedge_sph_count = floor(5*rand_d01(rc))+1; +			xform->wedge_sph_swirl = rand_d01(rc); +			break; + +		case VAR_WHORL: +			xform->whorl_inside = rand_d01(rc); +			xform->whorl_outside = rand_d01(rc); +			break; + +		case VAR_WAVES2: +			xform->waves2_scalex = 0.5 + rand_d01(rc); +			xform->waves2_scaley = 0.5 + rand_d01(rc); +			xform->waves2_freqx = 4 * rand_d01(rc); +			xform->waves2_freqy = 4 * rand_d01(rc); +			break;          + +		case VAR_AUGER: +			xform->auger_sym = 0; +			xform->auger_weight = 0.5 + rand_d01(rc)/2.0; +			xform->auger_freq = floor(5*rand_d01(rc))+1; +			xform->auger_scale = rand_d01(rc); +			break;          + +		case VAR_FLUX: +			xform->flux_spread = 0.5 + rand_d01(rc)/2.0; +			break; + +		case VAR_MOBIUS: +			xform->mobius_re_a = rand_d11(rc); +			xform->mobius_im_a = rand_d11(rc); +			xform->mobius_re_b = rand_d11(rc); +			xform->mobius_im_b = rand_d11(rc); +			xform->mobius_re_c = rand_d11(rc); +			xform->mobius_im_c = rand_d11(rc); +			xform->mobius_re_d = rand_d11(rc); +			xform->mobius_im_d = rand_d11(rc); +			break; +	} +} + +/*	Fill xform with random values + */ +void xform_rand (flam3_xform * const xform, const bool add_post, +		const unsigned int max_var, randctx * const rc) { +	assert (xform != NULL); +	assert (rc != NULL); + +	/* XXX: the original code alternates between 0/1 for every xform */ +	xform->color = rand_bool (rc) ? 1.0 : 0.0; + +	for (unsigned int j = 0; j < 3; j++) { +		for (unsigned int k = 0; k < 2; k++) { +			xform->c[j][k] = rand_d11(rc); +			if (add_post) { +				xform->post[j][k] = rand_d11(rc); +			} else { +				xform->post[j][k] = (double)(k==j); +			} +		} +	} + +	memset (xform->var, 0, sizeof (*xform->var)); +	for (unsigned int i = 0; i < max_var; i++) { +		const unsigned int v = rand_mod (rc, flam3_nvariations); +		double w; +		do { +			w = rand_d01 (rc); +		} while (w == 0.0); +		xform->var[v] += w; +		random_xform_param (xform, v, rc); + +		/* small number of variations is more likely */ +		if (rand_bool (rc)) { +			break; +		} +	} + +	/* Normalize weights to 1.0 total. */ +	normalize (xform->var, flam3_nvariations); +} + diff --git a/genome.h b/genome.h new file mode 100644 index 0000000..deac97f --- /dev/null +++ b/genome.h @@ -0,0 +1,25 @@ +/* +    Copyright (C) 1992-2009 Spotworks LLC +	              2015 pucket contributors + +    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/>. +*/ + +#pragma once + +#include "flam3.h" + +void xform_rand (flam3_xform * const xform, const bool add_post, +		const unsigned int max_var, randctx * const rc); + @@ -25,6 +25,8 @@  #include "private.h"  #include "img.h"  #include "rect.h" +#include "math.h" +#include "genome.h"  #define streq(a,b) (strcmp (a, b) == 0) @@ -93,7 +95,7 @@ static void do_render (const render_arguments * const arguments) {  	rand_seed(&rc);  	int ncps; -	flam3_genome * const cps = flam3_parse_from_file (stdin, NULL, +	flam3_genome * const cps = flam3_parse_xml2 (STDIN_FILENO,  			flam3_defaults_on, &ncps, &rc);  	if (cps == NULL) {  		fprintf(stderr,"error reading genomes from file\n"); @@ -141,9 +143,9 @@ static void print_genome (flam3_genome * const genome) {  }  typedef struct { -	int symmetry;  	const char *palette; -	unsigned int width, height; +	unsigned int width, height, max_xforms, max_var; +	double post_likelihood, final_likelihood, symmetry_likelihood;  } random_arguments;  static error_t parse_random_opt (int key, char *arg, @@ -170,6 +172,16 @@ static error_t parse_random_opt (int key, char *arg,  			break;  		} +		case 'x': { +			int i = atoi (arg); +			if (i <= 0) { +				argp_error (state, "Max xforms must be > 0"); +			} else { +				arguments->max_xforms = i; +			} +			break; +		} +  		case ARGP_KEY_ARG:  			if (state->arg_num > 0) {  				return ARGP_ERR_UNKNOWN; @@ -229,8 +241,41 @@ static void do_random (const random_arguments * const arguments) {  	assert (bret);  	flam3_genome genome; -	int ivars = flam3_variation_random; -	flam3_random (&genome, &ivars, 1, arguments->symmetry, 0, &pc, &rc); +	clear_cp (&genome,flam3_defaults_on); + +	genome.hue_rotation = rand_mod(&rc, 8) ? 0.0 : rand_d01(&rc); +	const palette * const p = palette_random (&pc, &rc); +	assert (p != NULL); +	palette_copy (p, &genome.palette); +	palette_rotate_hue (&genome.palette, genome.hue_rotation); +	genome.interpolation = flam3_interpolation_linear; +	genome.palette_interpolation = flam3_palette_interpolation_hsv; +	genome.rotate = rand_d01 (&rc) * 360.0; + +	unsigned int nxforms = rand_mod (&rc, arguments->max_xforms) + 1; +	flam3_add_xforms(&genome,nxforms,0,0); +	/* Add a final xform 15% of the time */ +	const bool add_final = rand_d01(&rc) < arguments->final_likelihood; +	if (add_final) { +		flam3_add_xforms(&genome,1,0,1); +		++nxforms; +	} + +	/* Loop over xforms */ +	assert (nxforms > 0); +	for (unsigned int i = 0; i < nxforms; i++) { +		flam3_xform * const xform = &genome.xform[i]; +		const bool add_post = rand_d01 (&rc) < arguments->post_likelihood; +		xform_rand (xform, add_post, arguments->max_var, &rc); +		xform->density = 1.0 / nxforms; +		xform->color_speed = 0.5; +		xform->animate = 1.0; +	} + +	/* Randomly add symmetry (but not if we've already added a final xform) */ +	if (rand_d01(&rc) < arguments->symmetry_likelihood && !add_final) { +		flam3_add_symmetry(&genome, 0, &rc); +	}  	/* random resets genome, adjust before finding appropriate bbox */  	genome.width = arguments->width; @@ -295,7 +340,7 @@ static void do_mutate (const mutate_arguments * const arguments) {  	rand_seed(&rc);  	int ncps; -	flam3_genome * const cps = flam3_parse_from_file (stdin, NULL, +	flam3_genome * const cps = flam3_parse_xml2 (STDIN_FILENO,  			flam3_defaults_on, &ncps, &rc);  	if (cps == NULL) {  		fprintf(stderr,"error reading genomes from file\n"); @@ -309,7 +354,7 @@ static void do_mutate (const mutate_arguments * const arguments) {  	flam3_genome * const genome = &cps[0]; -	int ivars = flam3_variation_random; +	int ivars = 0;  	const double speed = 1.0;  	flam3_mutate (genome, arguments->method, &ivars, 1, arguments->symmetry,  			speed, &pc, &rc); @@ -362,7 +407,7 @@ static void do_cross (const cross_arguments * const arguments) {  	rand_seed(&rc);  	int ncps; -	flam3_genome * const cps = flam3_parse_from_file (stdin, NULL, +	flam3_genome * const cps = flam3_parse_xml2 (STDIN_FILENO,  			flam3_defaults_on, &ncps, &rc);  	if (cps == NULL) {  		fprintf(stderr,"error reading genomes from file\n"); @@ -449,6 +494,7 @@ int main (int argc, char **argv) {  		argp_parse (&argp, argc, argv, 0, NULL, &arguments);  		do_cross (&arguments); +#if 0  	} else if (streq (command, "mutate")) {  		const struct argp_option options[] = {  				{"method", 'm', "XXX", OPTION_ARG_OPTIONAL, "Mutation method" }, @@ -467,11 +513,13 @@ int main (int argc, char **argv) {  		argp_parse (&argp, argc, argv, 0, NULL, &arguments);  		do_mutate (&arguments); +#endif  	} else if (streq (command, "random")) {  		/* generate random genome */  		const struct argp_option options[] = { -				{"height", 'h', "pixels", 0, "Output flame height" }, -				{"width", 'w', "pixels", 0, "Output flame width" }, +				{"height", 'h', "pixels", 0, "Output flame height (1000)" }, +				{"width", 'w', "pixels", 0, "Output flame width (1000)" }, +				{"max-xforms", 'x', "number", 0, "Max number of xforms (6)" },  				{ 0 },  				};  		const char doc[] = PACKAGE "-random -- a fractal flame generator"; @@ -481,10 +529,14 @@ int main (int argc, char **argv) {  				};  		random_arguments arguments = { -				.symmetry = 0,  				.palette = "flam3-palettes.xml",  				.width = 1000,  				.height = 1000, +				.max_xforms = 6, +				.max_var = flam3_nvariations, +				.post_likelihood = 0.4, +				.final_likelihood = 0.15, +				.symmetry_likelihood = 0.25,  				};  		argp_parse (&argp, argc, argv, 0, NULL, &arguments); @@ -19,6 +19,7 @@  #pragma once  #include <math.h> +#include <assert.h>  #include "build/config.h" @@ -79,6 +80,20 @@ inline double sum(const double2 in) {  	return in[0] + in[1];  } +inline void normalize (double * const a, const size_t n) { +	double sum = 0.0; +	for (unsigned int j = 0; j < n; j++) { +		sum += a[j]; +	} +	assert (sum > 0.0); + +	for (unsigned int j = 0; j < n; j++) { +		a[j] /= sum; +	} +} + +#define max(a,b) ((a) > (b) ? (a) : (b)) +  /*	Vector wrapping function, could be replaced by true vector functions later   */ @@ -216,7 +216,7 @@ int flam3_interp_missing_colors(flam3_genome *cp) {  #endif -void scan_for_flame_nodes(xmlNode *cur_node, char *parent_file, int default_flag, flam3_genome **all_cps, int *all_ncps, randctx * const rc) { +void scan_for_flame_nodes(xmlNode *cur_node, int default_flag, flam3_genome **all_cps, int *all_ncps, randctx * const rc) {     xmlNode *this_node = NULL;     flam3_genome loc_current_cp; @@ -262,7 +262,7 @@ void scan_for_flame_nodes(xmlNode *cur_node, char *parent_file, int default_flag        } else {           /* Check all of the children of this element */ -         scan_for_flame_nodes(this_node->children, parent_file, default_flag, all_cps, all_ncps, rc); +         scan_for_flame_nodes(this_node->children, default_flag, all_cps, all_ncps, rc);        }     } @@ -26,7 +26,7 @@ int var2n(const char *s);  int flam3_parse_hexformat_colors(char *colstr, flam3_genome *cp, int numcolors, int chan);  #endif -void scan_for_flame_nodes(xmlNode *cur_node, char *parent_file, int default_flag, flam3_genome **all_cp, int *all_ncps, randctx * const); +void scan_for_flame_nodes(xmlNode *cur_node, int default_flag, flam3_genome **all_cp, int *all_ncps, randctx * const);  int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, randctx * const);  int parse_xform_xml(xmlNode *chld_node,flam3_xform *this_xform, int *num_xaos,                       flam3_chaos_entry **xaos, int numstd, int motionxf); @@ -22,5 +22,5 @@ def configure(conf):      conf.write_config_header ('config.h')  def build(bld): -    bld.program (features='c cprogram', source='flam3.c parser.c variations.c interpolation.c palettes.c png.c random.c rect.c main.c', target='pucket', use='xml2 png amdlibm') +    bld.program (features='c cprogram', source='flam3.c parser.c variations.c interpolation.c palettes.c png.c random.c rect.c main.c genome.c', target='pucket', use='xml2 png amdlibm') | 
