Initial import
This commit is contained in:
commit
4304edc0f0
14 changed files with 1268 additions and 0 deletions
361
julia.c
Normal file
361
julia.c
Normal file
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <complex.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "criticals.h"
|
||||
#include "palette.h"
|
||||
#include "pnmout.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "fun.h"
|
||||
|
||||
struct color contour_color = { 0 };
|
||||
static long double bailout = 1e100,
|
||||
epsilon = 1e-8,
|
||||
sec_w = 4.0,
|
||||
contour = 0.0005L;
|
||||
static unsigned long niters = 250;
|
||||
|
||||
static void
|
||||
print_critical_points(void)
|
||||
{
|
||||
long double complex z;
|
||||
size_t i, n;
|
||||
|
||||
n = ncriticals();
|
||||
fprintf(stderr, "Critical points:\n");
|
||||
for (i = 0; i < n; i++) {
|
||||
z = get_critical(i);
|
||||
fprintf(stderr, "%4zu. (%.20Lf, %.20Lf)\n", i, creall(z),
|
||||
cimagl(z));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tends_to_critical(long double complex z, long double *t)
|
||||
{
|
||||
long double d;
|
||||
size_t i, n;
|
||||
|
||||
n = ncriticals();
|
||||
for (i = 0; i < n; i++) {
|
||||
d = cabsl(z - get_critical(i));
|
||||
if (d < epsilon) {
|
||||
*t = d;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
iterate(long double complex z, long double complex c, long double *rit)
|
||||
{
|
||||
long double complex dz = 1.0L;
|
||||
long double t;
|
||||
unsigned long ci, i;
|
||||
|
||||
for (i = 0; i < niters && cabsl(z) < bailout; i++) {
|
||||
dz = df(z) * dz;
|
||||
z = f(z) + c;
|
||||
|
||||
if (tends_to_critical(z, &t)) {
|
||||
*rit = logl(logl(t) / logl(epsilon)) / logl(2.0L);
|
||||
return fabsl(logl(t)) * t < sec_w * contour * cabsl(dz)
|
||||
? -1 : i;
|
||||
}
|
||||
}
|
||||
|
||||
t = cabsl(z);
|
||||
if (t >= bailout) {
|
||||
*rit = logl(logl(t) / logl(bailout)) / logl(2.0L);
|
||||
return fabsl(logl(t)) * t < sec_w * contour * cabsl(dz)
|
||||
? -1 : i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long
|
||||
fast_iterate(long double complex z, long double complex c, long double *rit)
|
||||
{
|
||||
long double t;
|
||||
unsigned long ci, i;
|
||||
|
||||
for (i = 0; i < niters && cabsl(z) < bailout; i++) {
|
||||
z = f(z) + c;
|
||||
|
||||
if (tends_to_critical(z, &t)) {
|
||||
*rit = logl(logl(t) / logl(epsilon)) / logl(2.0L);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
t = cabsl(z);
|
||||
if (t >= bailout) {
|
||||
*rit = logl(logl(t) / logl(bailout)) / logl(2.0L);
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s julia [-L] [-x julia_x] [-y julia_y]\n"
|
||||
" [-n niters] [-h height] [-w width] [-z zoom]\n"
|
||||
" [-a center_x] [-b center_y] [-l light_intensity]\n"
|
||||
" [-d density] [-c contour]\n",
|
||||
xgetprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
julia_main(int argc, char *argv[])
|
||||
{
|
||||
struct color *palette;
|
||||
struct {
|
||||
long long it;
|
||||
long double rit;
|
||||
} *rescache;
|
||||
char *end;
|
||||
struct color color;
|
||||
long double complex crit, julia, z;
|
||||
long double julia_x = 0.0,
|
||||
julia_y = 0.0,
|
||||
cen_x = 0.0,
|
||||
cen_y = 0.0,
|
||||
density = 28.3L,
|
||||
light_intensity = 84.3L,
|
||||
displacement = 0,
|
||||
zoom = 1.0,
|
||||
light, light_x, light_y, light_z, rit, sec_h, zx, zy;
|
||||
intmax_t v;
|
||||
long long it, idx, ritnum;
|
||||
unsigned int palette_size = 720,
|
||||
width = 640,
|
||||
height = 400,
|
||||
i, j;
|
||||
int ch, do_light = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "a:b:c:d:h:Ll:n:w:x:y:z:")) != -1)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
errno = 0;
|
||||
cen_x = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-a: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
errno = 0;
|
||||
cen_y = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-b: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
errno = 0;
|
||||
contour = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0
|
||||
|| contour <= 0) {
|
||||
fprintf(stderr, "-c: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
errno = 0;
|
||||
density = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-d: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
errno = 0;
|
||||
v = strtoimax(optarg, &end, 0);
|
||||
if (end == optarg || *end != '\0' || errno != 0 ||
|
||||
v <= 0 || v >= 65536) {
|
||||
fprintf(stderr, "-h: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
height = (unsigned int)v + 1;
|
||||
break;
|
||||
case 'L':
|
||||
do_light = 1;
|
||||
break;
|
||||
case 'l':
|
||||
errno = 0;
|
||||
light_intensity = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-l: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
errno = 0;
|
||||
v = strtoimax(optarg, &end, 0);
|
||||
if (end == optarg || *end != '\0' || errno != 0 ||
|
||||
v <= 0 || v >= ULONG_MAX) {
|
||||
fprintf(stderr, "-n: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
niters = (unsigned long)v;
|
||||
break;
|
||||
case 'w':
|
||||
errno = 0;
|
||||
v = strtoimax(optarg, &end, 0);
|
||||
if (end == optarg || *end != '\0' || errno != 0 ||
|
||||
v <= 0 || v >= 65536) {
|
||||
fprintf(stderr, "-w: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
width = (unsigned int)v + 1;
|
||||
break;
|
||||
case 'x':
|
||||
errno = 0;
|
||||
julia_x = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-x: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
errno = 0;
|
||||
julia_y = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-y: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
errno = 0;
|
||||
zoom = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0
|
||||
|| zoom <= 0) {
|
||||
fprintf(stderr, "-z: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc > 1)
|
||||
usage();
|
||||
|
||||
palette = palette_gen(palette_size);
|
||||
|
||||
if ((rescache = malloc(sizeof(*rescache) * width * height)) == NULL) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (do_light) {
|
||||
long double angle_xy, angle_z;
|
||||
angle_xy = drand48() * 2.0L * 3.14159265358979323846L;
|
||||
angle_z = (0.2L + 0.6L * drand48()) * 3.14159265358979323846L;
|
||||
light_x = cosl(angle_xy) * sinl(angle_z);
|
||||
light_y = sinl(angle_xy) * sinl(angle_z);
|
||||
light_z = cosl(angle_z);
|
||||
}
|
||||
|
||||
sec_h = sec_w * height / (long double)width;
|
||||
julia = julia_x + I * julia_y;
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
zy = cen_y + (0.5 - i / (long double)height) * sec_h;
|
||||
for (j = 0; j < width; j++) {
|
||||
zx = cen_x + (j / (long double)width - 0.5L) * sec_w;
|
||||
z = zx + I * zy;
|
||||
if (behaves_critical(df, ddf, z, &crit, bailout,
|
||||
epsilon))
|
||||
add_critical_point(crit);
|
||||
}
|
||||
}
|
||||
|
||||
print_critical_points();
|
||||
|
||||
sec_w /= zoom; sec_h /= zoom;
|
||||
for (i = 0; i < height; i++) {
|
||||
zy = cen_y + (0.5L - i / (long double)height) * sec_h;
|
||||
for (j = 0; j < width; j++) {
|
||||
zx = cen_x + (j / (long double)width - 0.5L) * sec_w;
|
||||
z = zx + I * zy;
|
||||
it = iterate(z, julia, &rit);
|
||||
rescache[i * width + j].it = it;
|
||||
rescache[i * width + j].rit = rit;
|
||||
}
|
||||
}
|
||||
|
||||
pnmout_header(stdout, width - 1, height - 1);
|
||||
for (i = 0; i < height - 1; i++) {
|
||||
for (j = 0; j < width - 1; j++) {
|
||||
it = rescache[i * width + j].it;
|
||||
rit = rescache[i * width + j].rit;
|
||||
|
||||
if (it < 0)
|
||||
color = contour_color;
|
||||
else {
|
||||
ritnum = (it - rit) * density;
|
||||
if (do_light) {
|
||||
long double lxrn, lyrn, l, lx, ly, lz;
|
||||
lxrn = rescache[i * width + j + 1].it
|
||||
- rescache[i * width + j + 1].rit;
|
||||
lyrn = rescache[(i + 1) * width + j].it
|
||||
- rescache[(i + 1) * width + j].rit;
|
||||
lx = -sec_h * (lxrn - it + rit);
|
||||
ly = sec_w * (lyrn - it + rit);
|
||||
lz = sec_w * sec_h;
|
||||
l = sqrtl(lx * lx + ly * ly + lz * lz);
|
||||
light = (light_x * lx + light_y * ly
|
||||
+ light_z * lz) / l;
|
||||
ritnum += light * light_intensity;
|
||||
}
|
||||
idx = (long long)ritnum
|
||||
+ 1000000 * palette_size + displacement;
|
||||
color = palette[idx % palette_size
|
||||
+ (idx < 0 ? palette_size : 0)];
|
||||
}
|
||||
|
||||
pnmout_pixel(stdout, color);
|
||||
}
|
||||
}
|
||||
|
||||
free(rescache);
|
||||
free(palette);
|
||||
|
||||
return !(fflush(stdout) == 0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue