Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e61121c75 | ||
|
|
a9a9a247ab | ||
|
|
f34e398223 |
+32
-75
@@ -72,26 +72,15 @@ fn kind_label(kind: FractalKind) -> &'static str {
|
||||
/// Multibrot.
|
||||
fn kind_formula(kind: FractalKind, power: u32) -> String {
|
||||
match kind {
|
||||
FractalKind::Mandelbrot => "z → z² + c".to_string(),
|
||||
FractalKind::BurningShip => "z → (|Re z| + i|Im z|)² + c".to_string(),
|
||||
FractalKind::Tricorn => "z → conj(z)² + c".to_string(),
|
||||
FractalKind::Multibrot => format!("z → z^{power} + c"),
|
||||
FractalKind::Celtic => "z → |Re(z²)| + i·Im(z²) + c".to_string(),
|
||||
FractalKind::Perpendicular => "z → (x² − y²) − 2x|y|i + c".to_string(),
|
||||
FractalKind::Buffalo => "z → |Re(z²)| − i|Im(z²)| + c".to_string(),
|
||||
FractalKind::Phoenix => "z → z² + c + p·z_prev".to_string(),
|
||||
FractalKind::Lambda => "z → λ·z(1 − z)".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorten a long decimal string for compact display, keeping the leading
|
||||
/// (most significant) digits and marking the cut with "…".
|
||||
fn truncate_digits(s: &str, max_len: usize) -> String {
|
||||
if s.chars().count() <= max_len {
|
||||
s.to_string()
|
||||
} else {
|
||||
let head: String = s.chars().take(max_len).collect();
|
||||
format!("{head}…")
|
||||
FractalKind::Mandelbrot => "z = z² + c".to_string(),
|
||||
FractalKind::BurningShip => "z = (|Re(z)| + i|Im(z)|)² + c".to_string(),
|
||||
FractalKind::Tricorn => "z = conj(z)² + c".to_string(),
|
||||
FractalKind::Multibrot => format!("z = z^{power} + c"),
|
||||
FractalKind::Celtic => "z = |Re(z²)| + i·Im(z²) + c".to_string(),
|
||||
FractalKind::Perpendicular => "z = (x² − y²) − 2x|y|i + c".to_string(),
|
||||
FractalKind::Buffalo => "z = |Re(z²)| − i|Im(z²)| + c".to_string(),
|
||||
FractalKind::Phoenix => "z = z² + c + p·z_prev".to_string(),
|
||||
FractalKind::Lambda => "z = λ·z(1 − z)".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1199,7 +1188,7 @@ impl FractalApp {
|
||||
.shadow(egui::Shadow::NONE)
|
||||
.show(ui, |ui| {
|
||||
if ui
|
||||
.button("ⓘ Info")
|
||||
.button("Fractal infos")
|
||||
.on_hover_text("Show details about the current fractal")
|
||||
.clicked()
|
||||
{
|
||||
@@ -1226,12 +1215,16 @@ impl FractalApp {
|
||||
.strong()
|
||||
.heading(),
|
||||
);
|
||||
let mode_label = match self.mode {
|
||||
FractalMode::Mandelbrot => {
|
||||
"Mandelbrot mode — parameter space (c varies per pixel, z₀ = 0)"
|
||||
}
|
||||
FractalMode::Julia => {
|
||||
"Julia mode — dynamical plane for a fixed c (z₀ varies per pixel)"
|
||||
let mode_label = if self.buddhabrot {
|
||||
"Buddhabrot mode — orbit density (random c, z₀ = 0)"
|
||||
} else {
|
||||
match self.mode {
|
||||
FractalMode::Mandelbrot => {
|
||||
"Mandelbrot mode — parameter space (c varies per pixel, z₀ = 0)"
|
||||
}
|
||||
FractalMode::Julia => {
|
||||
"Julia mode — dynamical plane for a fixed c (z₀ varies per pixel)"
|
||||
}
|
||||
}
|
||||
};
|
||||
ui.label(mode_label);
|
||||
@@ -1255,32 +1248,7 @@ impl FractalApp {
|
||||
}
|
||||
ui.separator();
|
||||
|
||||
if self.buddhabrot {
|
||||
ui.label("rendering: Buddhabrot (Monte-Carlo orbit density)");
|
||||
ui.label(format!(
|
||||
"sample caps: R {} / G {} / B {}",
|
||||
self.buddha_r_cap, self.buddha_g_cap, self.buddha_b_cap
|
||||
));
|
||||
} else {
|
||||
ui.label(format!(
|
||||
"magnification: {}×",
|
||||
format_magnification(self.view.magnification())
|
||||
));
|
||||
ui.label(format!(
|
||||
"iterations: {}{}",
|
||||
self.max_iterations,
|
||||
if self.auto_iterations { " (auto)" } else { "" }
|
||||
));
|
||||
ui.label(format!("precision: {} bits", self.view.precision_bits()));
|
||||
ui.label(format!(
|
||||
"center re: {}",
|
||||
truncate_digits(&self.center_re_edit, 24)
|
||||
));
|
||||
ui.label(format!(
|
||||
"center im: {}",
|
||||
truncate_digits(&self.center_im_edit, 24)
|
||||
));
|
||||
}
|
||||
ui.label(self.kind.description());
|
||||
});
|
||||
self.info_open = open;
|
||||
}
|
||||
@@ -1302,19 +1270,16 @@ impl FractalApp {
|
||||
ui.label(
|
||||
"A deep-zoom fractal explorer. It renders the Mandelbrot set \
|
||||
and several related fractals (Burning Ship, Tricorn, \
|
||||
Multibrot, Celtic, Perpendicular, Buffalo, Phoenix, Lambda), \
|
||||
and can zoom in far beyond what ordinary floating-point math \
|
||||
allows by using perturbation theory: one very precise \
|
||||
reference orbit is computed once, and every pixel on screen \
|
||||
is then rendered cheaply as a small offset from that shared \
|
||||
orbit.",
|
||||
Multibrot, Celtic, Perpendicular, Buffalo, Phoenix, Lambda).",
|
||||
);
|
||||
ui.add_space(4.0);
|
||||
ui.label(
|
||||
"Mandelbrot mode plots one point per pixel in parameter space \
|
||||
(does c escape?). Julia mode fixes c and instead varies the \
|
||||
starting point z₀ across the plane. Buddhabrot mode switches \
|
||||
to a different, Monte-Carlo rendering of orbit density \
|
||||
"Each fractals can be rendered in different modes: \n\
|
||||
• Mandelbrot mode fixes z₀=0 and then for each pixel, set c as it's position \
|
||||
in the complex plane. \n\
|
||||
• Julia mode fixes c and instead varies the \
|
||||
starting point z₀ across the plane. \n\
|
||||
• Buddhabrot mode switches to a different, Monte-Carlo rendering of orbit density \
|
||||
instead of the ordinary escape-time set.",
|
||||
);
|
||||
ui.separator();
|
||||
@@ -1366,20 +1331,11 @@ impl FractalApp {
|
||||
ui.label("Toggle antialiasing (2×2)");
|
||||
ui.end_row();
|
||||
});
|
||||
ui.label(
|
||||
"Shortcuts are ignored while a text field (e.g. the center/zoom \
|
||||
edit boxes) has focus. Esc / F11 toggle fullscreen via the \
|
||||
browser or OS, as usual.",
|
||||
);
|
||||
ui.separator();
|
||||
|
||||
ui.heading("Tips");
|
||||
ui.label(
|
||||
"• The controls panel (top-left \"Menu\" button) holds the \
|
||||
fractal formula, coloring, animation, and export options.\n\
|
||||
• The bottom-left \"Info\" button shows details about what's \
|
||||
currently on screen.\n\
|
||||
• \"Copy link\" (in the panel) encodes the exact view so it \
|
||||
"• \"Copy link\" (in the panel) encodes the exact view so it \
|
||||
can be reopened later or sent to someone else.",
|
||||
);
|
||||
});
|
||||
@@ -1870,10 +1826,11 @@ impl FractalApp {
|
||||
ui.add(
|
||||
egui::DragValue::new(&mut self.export_scale)
|
||||
.range(1.0..=16.0)
|
||||
.speed(0.5),
|
||||
.speed(0.25)
|
||||
.custom_formatter(|x, _| format!("x{:.1}", x)),
|
||||
);
|
||||
ui.label(format!(
|
||||
"→ {}×{}",
|
||||
"= {}×{}",
|
||||
(self.last_size_px.x * self.export_scale) as u32,
|
||||
(self.last_size_px.y * self.export_scale) as u32,
|
||||
));
|
||||
|
||||
@@ -37,6 +37,26 @@ pub enum FractalKind {
|
||||
Lambda = 8,
|
||||
}
|
||||
|
||||
impl FractalKind {
|
||||
pub fn description(&self) -> &str {
|
||||
match self {
|
||||
FractalKind::Mandelbrot => {
|
||||
"The Mandelbrot set is the most famous fractal set, obtained with the simplest escape-time formula. This set represents all Julia fractals: each points of the Mandelbrot set is related to a specific Julia fractal."
|
||||
}
|
||||
FractalKind::BurningShip => {
|
||||
"A variation of the famous Mandelbrot set, using absolute values on the real and imaginary part of each iterations."
|
||||
}
|
||||
FractalKind::Tricorn => "The Tricorn set is obtained using the same formula as the Mandelbrot set, taking the complex conjugate of the previous iteration.",
|
||||
FractalKind::Multibrot => "Multibrot use the same formula as the Mandelbrot set, with a bigger exposant.",
|
||||
FractalKind::Celtic => "",
|
||||
FractalKind::Perpendicular => "",
|
||||
FractalKind::Buffalo => "",
|
||||
FractalKind::Phoenix => "",
|
||||
FractalKind::Lambda => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reference orbit escapes once |Z|^2 exceeds this. Kept larger than the pixel
|
||||
/// bailout so pixels escaping alongside the reference can still reach their
|
||||
/// bailout before the stored orbit runs out.
|
||||
|
||||
Reference in New Issue
Block a user