wallswitch 0.60.11

randomly selects wallpapers for multiple monitors
Documentation
//! Julia Set fractal generator overlay.
//!
//! This module provides the implementation of the Julia Set fractal renderer,
//! using pre-programmed coordinate presets. It generates mathematical overlays
//! dynamically fitted to the display dimensions and blends them using high-contrast
//! dual-tone chromatic borders and 3D shadow depth offsets.

use std::f64::consts::PI;

use crate::{
    ColorRGB, Complex, FractalConfig, FractalDescriptor, FractalPreset, MAX_ITERATIONS,
    MIN_ITERATIONS, Monitor, NEON_PALETTES, ProceduralEffect, RandomExt, color_distance_estimator,
    get_random_integer, julia_escape, optimize_fractal_viewport, rand_f64,
};

/// A procedural generator for rendering Julia Set fractals onto desktop backgrounds.
pub struct JuliaGenerator {
    pub preset: FractalPreset,
    pub config: FractalConfig,
}

impl Default for JuliaGenerator {
    fn default() -> Self {
        Self {
            preset: FractalPreset {
                center: Complex::new(-0.7, 0.27015),
                fractal_name: "Classic denderite",
                effect_name: ProceduralEffect::JuliaSet,
            },
            config: FractalConfig {
                scan_iterations: get_random_integer(MIN_ITERATIONS, MAX_ITERATIONS),
                color_palette: NEON_PALETTES[5],
                zoom: 3.0,
                rotation: Complex::one(),
            },
        }
    }
}

impl FractalDescriptor for JuliaGenerator {
    #[inline(always)]
    fn config(&self) -> &FractalConfig {
        &self.config
    }

    #[inline(always)]
    fn center(&self) -> Complex {
        self.preset.center
    }

    #[inline(always)]
    fn is_julia(&self) -> bool {
        true
    }

    #[inline(always)]
    fn render_pixel(&self, z_init: Complex, scale: f64, _max_radius: f64) -> (ColorRGB, f64, f64) {
        let (i, z, dz) = julia_escape(z_init, self.preset.center, self.config.scan_iterations);
        color_distance_estimator(
            i,
            self.config.scan_iterations,
            z,
            dz,
            scale,
            self.config.color_palette,
        )
    }

    fn info_text(&self) -> String {
        format!(
            "fractal [{}]\n\
            f(z) = z^2 + c, where c = {:8.5} {:+7.5}i (iter = {:4}, zoom = {:.2}), color: {}",
            self.preset.fractal_name,
            self.preset.center.re,
            self.preset.center.im,
            self.config.scan_iterations,
            self.config.zoom,
            self.config.color_palette
        )
    }
}

impl JuliaGenerator {
    /// Generates a randomized Julia Set configuration fitted to monitor proportions.
    pub fn random(monitor: &Monitor) -> Self {
        let width = monitor.resolution.width as u32;
        let height = monitor.resolution.height as u32;

        let presets = [
            FractalPreset {
                center: Complex::new(-0.4, 0.6),
                fractal_name: "Classic cloud swirls",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.8, 0.156),
                fractal_name: "Detailed spirals",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.7269, 0.1889),
                fractal_name: "Lace structures",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.75, 0.11),
                fractal_name: "Feathery branches",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.1, 0.651),
                fractal_name: "Cosmic dust style",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(0.355, 0.355),
                fractal_name: "Spiral galaxy arms",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.4, -0.59),
                fractal_name: "Swirling vortexes",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.54, 0.54),
                fractal_name: "Ornamental lace borders",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.835, -0.2321),
                fractal_name: "Lightning rods",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.77269, 0.12428),
                fractal_name: "Coral reefs",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.51251, 0.5213),
                fractal_name: "Fine lace filaments",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.55, 0.55),
                fractal_name: "Intricate leaf outlines",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.624, 0.435),
                fractal_name: "Crystalline snowflake patterns",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.12, 0.85),
                fractal_name: "Flowing plasma plumes",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.391, -0.587),
                fractal_name: "Swirling storm clouds",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.73, 0.21),
                fractal_name: "Feathery dendritic lace",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.81, 0.2),
                fractal_name: "Spiral galaxy filaments",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.68, 0.34),
                fractal_name: "Delicate coral spirals",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.76, 0.08),
                fractal_name: "Lightning tree branches",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(0.285, 0.01),
                fractal_name: "Cosmic galaxy vortex swirls",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.8, 0.17),
                fractal_name: "Spidery lace denderites",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.7269, -0.1889),
                fractal_name: "Conjugate lace structures",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.835, 0.2321),
                fractal_name: "Conjugate lightning rods",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.75, 0.05),
                fractal_name: "Dense branching coral reef",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.70176, 0.3842),
                fractal_name: "Conjugate dragon-like curves",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.8, 0.16),
                fractal_name: "Deep sea coral spirals",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.722, 0.246),
                fractal_name: "Dendritic pine branch variation",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.11, 0.655),
                fractal_name: "Triple helix rotational cosmic swirls",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.52519, 0.5215),
                fractal_name: "Intertwined Gothic Cathedral window arches",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(0.28, 0.008),
                fractal_name: "Centrifugal pinwheel galaxy vortex generator",
                effect_name: ProceduralEffect::JuliaSet,
            },
            FractalPreset {
                center: Complex::new(-0.83, -0.232),
                fractal_name: "Sharp crystalline glacial ice column needles",
                effect_name: ProceduralEffect::JuliaSet,
            },
        ];

        let selected_preset = presets.choose().copied().unwrap_or(presets[0]);
        let color_palette = NEON_PALETTES.choose().copied().unwrap_or(NEON_PALETTES[0]);
        let radians = rand_f64() * 2.0 * PI;

        let mut julia = Self {
            preset: selected_preset,
            config: FractalConfig {
                scan_iterations: get_random_integer(MIN_ITERATIONS, MAX_ITERATIONS),
                color_palette,
                zoom: 3.0,
                rotation: Complex::from_polar(1.0, radians),
            },
        };

        julia.optimize_fit(width, height);
        julia
    }

    /// Automatically optimizes the framing boundary parameters of the viewport.
    pub fn optimize_fit(&mut self, width: u32, height: u32) {
        let c_abs = self.preset.center.abs();
        let r_bound = (1.0 + (1.0 + 4.0 * c_abs).sqrt()) / 2.0;
        let search_limit = r_bound * 1.2;

        let steps = 128;
        let scan_iterations = self.config.scan_iterations;
        let center = self.preset.center;

        let (best_zoom, best_rotation) = optimize_fractal_viewport(
            width,
            height,
            search_limit,
            steps,
            self.config.rotation,
            |z| {
                let (i, _, _) = julia_escape(z, center, scan_iterations);
                i > 3 && i < scan_iterations
            },
        );

        let padding_factor = 1.10;

        if best_zoom < f64::MAX {
            self.config.zoom = best_zoom * padding_factor;
            self.config.rotation = best_rotation;
        } else {
            self.config.zoom = 2.0 * r_bound * padding_factor;
        }
    }
}

#[cfg(test)]
mod tests_julia {
    use super::*;

    #[test]
    fn test_julia_generation_random() {
        let monitor = Monitor::default();
        let julia = JuliaGenerator::random(&monitor);
        assert!(julia.config.zoom > 0.0);
        assert_eq!(julia.preset.effect_name, ProceduralEffect::JuliaSet);
    }
}