summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flam3.c525
-rw-r--r--flam3.h16
-rw-r--r--genome.c299
-rw-r--r--genome.h25
-rw-r--r--main.c74
-rw-r--r--math.h15
-rw-r--r--parser.c4
-rw-r--r--parser.h2
-rw-r--r--wscript2
9 files changed, 418 insertions, 544 deletions
diff --git a/flam3.c b/flam3.c
index bf0b124..e974b50 100644
--- a/flam3.c
+++ b/flam3.c
@@ -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);
diff --git a/flam3.h b/flam3.h
index 58b6343..8dc4595 100644
--- a/flam3.h
+++ b/flam3.h
@@ -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);
+
diff --git a/main.c b/main.c
index ecd487a..61ad772 100644
--- a/main.c
+++ b/main.c
@@ -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);
diff --git a/math.h b/math.h
index dc72d87..fa49d09 100644
--- a/math.h
+++ b/math.h
@@ -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
*/
diff --git a/parser.c b/parser.c
index f28bad8..20eaaa9 100644
--- a/parser.c
+++ b/parser.c
@@ -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);
}
}
diff --git a/parser.h b/parser.h
index e76f812..5fa1923 100644
--- a/parser.h
+++ b/parser.h
@@ -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);
diff --git a/wscript b/wscript
index 4841945..3a0b341 100644
--- a/wscript
+++ b/wscript
@@ -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')