Beginner – Rust code of a tree fractal becomes more idiomatic

I've just picked up Rust and this is my first program (at least more than 10 lines), so I'm looking for constructs that are more primitive and natural for Rust. I'm from a C ++ / Python background. If there are more optimizations at compile time, that would be nice too, since I'm interested in zero overhead abstractions.

use std::fs::File;
use std::io::Write;
use std::cmp;

const SCALING_FACTOR: f64 = 1.4 as f64;

#(derive(Clone))
struct RGB {
    red: u8,
    green: u8,
    blue: u8
}

fn serialize_rgb(pixels: &Vec, size: usize) -> Vec {
    // for saving to a file. Is there any way we could do this
    // without constructing a new array? Would be much faster
    let mut output: Vec = Vec::with_capacity(size * 3);
    for pix in pixels {
        output.push(pix.red);
        output.push(pix.green);
        output.push(pix.blue);
    }
    output
}

struct Canvas {
    // Using 1D array so the bytes are together in memory, should be more efficient than Vec
    // since that would store pointers to vectors?
    pixels: Vec,
    width: i32,
    height: i32
}

impl Canvas {
    fn set_colour(&mut self, x: i32, y: i32, colour: &RGB) {
        // make this more natural? In C++ you can overload () to get a functor
        if x > 0 && y > 0 &&  x < self.width && y <  self.height {
            self.pixels((self.width * y + x) as usize) = colour.clone();
        }
    }

    fn write_to_file(&mut self, filename: &str) {
        let mut file = init_ppm(filename, self.width, self.height);
        file.write_all(&serialize_rgb(&self.pixels, (self.width * self.height) as usize)).expect("error");
        /* slow
        for pixel in &self.pixels {
            file.write_all(&(pixel.red, pixel.green, pixel.blue)).expect("error writing to a file");
        }*/
    }

    fn new(width: i32, height: i32) -> Canvas {
        Canvas {
            width,
            height,
            pixels: vec!(RGB{red:0, green:0, blue:0}; (width * height) as usize)
        }
    }

    fn draw_square(&mut self, center: &Point, width: i32, colour: &RGB) {
        for y in cmp::max(0, center.y - width) .. cmp::min(self.height, center.y + width) {
            for x in cmp::max(0, center.x - width) .. cmp::min(self.width, center.x + width) {
                self.set_colour(x ,y, &colour);
            }
        }
    }

    fn draw_line(&mut self, from: &Point, to: &Point, width: i32, colour: &RGB) {
        // function that connects two points on the grid with a line
        if from.x == to.x { // vertical lines
            let startx = cmp::max(from.x - width, 0);
            let endx = cmp::min(from.x + width, self.width);
            let endy = cmp::max(from.y, to.y) + 1;
            let starty = cmp::min(from.y, to.y);
            for y in starty .. endy {
                for x in  startx .. endx {
                    self.set_colour(x, y, colour);
                }

            }
        }
        else {
            let k = (to.y - from.y) as f64 / (to.x - from.x) as f64;
            let n = to.y as f64 - k * to.x as f64;
            let lower = cmp::min(from.x, to.x);
            let upper = cmp::max(from.x, to.x) + 1;
            for x in lower .. upper {
                // We colour y's as a function of x's
                self.draw_square(
                    &Point {x: x, y: (k * x as f64 + n) as i32},
                    width,
                    colour
                );
            }
            if k.abs() > 1.0 {
                // for steep lines, we also have to consider x as a function of y to get good results
                let lower = cmp::min(from.y, to.y);
                let upper = cmp::max(from.y, to.y) + 1;
                for y in lower .. upper {
                    self.draw_square(
                        &Point {x: ((y as f64 - n) / k) as i32, y: y},
                        width,
                        colour
                    );
                }
            }
        }
    }

}

fn rotate_point(center: &Point, point: &Point, angle: f64) -> Point {
    // also scales down a bit
    let (sin, cos) = angle.sin_cos();
    let translated = Point {x: ((point.x - center.x) as f64 / SCALING_FACTOR) as i32,
                            y: ((point.y - center.y) as f64 / SCALING_FACTOR) as i32};
    let rotated = Point {x: (translated.x as f64 * cos - translated.y as f64 * sin) as i32,
                         y: (translated.x as f64 * sin + translated.y as f64 * cos) as i32
    };
    Point {x: rotated.x + center.x, y: rotated.y + center.y}
}

fn init_ppm(filename: &str, width: i32, height: i32) -> File {
    let mut file = File::create(format!("{}.ppm",filename)).expect("couldn't create");
    file.write_all(format!("P6 {} {} 255 ", width, height).as_bytes()).expect("error writing to a file");
    file
}

struct Point {
    x: i32,
    y: i32
}

fn main() {
    const WIDTH: i32 = 1500;
    const HEIGHT: i32 = 1500;
    let mut picture = Canvas::new(WIDTH, HEIGHT);
    draw_tree(&mut picture,
              &Point {x: WIDTH/2, y: HEIGHT},
              &Point {x: WIDTH/2, y: 3*HEIGHT/4},
              15,
              &RGB {red: 255, blue: 255, green: 255},
              0.6,
              2);
    picture.write_to_file("test");
}


fn draw_tree(mut canvas: &mut Canvas, prev: &Point, next: &Point, iter: i32, colour: &RGB, angle: f64, branches: i32) {
    // recursively generates branches.
    if iter == 0 {
        return;
    }
    canvas.draw_line(prev, next, 1, colour);
    let prev = Point {x: 2 * next.x - prev.x, y: 2 * next.y - prev.y};

    if branches % 2 == 1 {
        draw_tree(&mut canvas, &next, &rotate_point(next, &prev, 0.0), iter - 1, colour, angle, branches);
    }
    for i in 1 .. branches / 2 + 1 {
        // colours are hardcoded currently but that's not really important
        let rot_left = rotate_point(next, &prev, i as f64 * angle);
        draw_tree(&mut canvas, &next, &rot_left, iter - 1, &RGB{red: 247, green: 97, blue: 74}, angle, branches);

        let rot_right = rotate_point(next, &prev, - i as f64 * angle);
        draw_tree(&mut canvas, &next, &rot_right, iter - 1, &RGB{red: 26, green: 121, blue: 244}, angle, branches);
    }
}

The final result of the code is a PPM image file test.ppm that looks binary tree picture as follows (depending on how you made the settings in main and SCALING_FACTOR)

ap.analyse von pdes – What is the geometric or dynamic meaning of a global attractor with an infinite fractal dimension?

In Efendiev-Ôtani's article: Infinite Dimensional Attractors for Parabolic Equations with p-Laplace in Heterogeneous Medium (Ann.I. H. Poincaré, AN 28, 2011) it is obtained that the fractal dimension of the global attractor is infinite. However, no geometric or dynamic consequences are achieved.

Original post:
https://www.researchgate.net/post/Was_is_the_geometric_or_dynamic_image_of_a_global_attractor_with_a_future_fractorial_image

gn.general topology – Fractal plane continuum with the order $ omega $?

continuum means compact and connected.

The order $ ord (x) $ from one point $ x $ in a continuum $ X $ is defined as the smallest ordinal number $ alpha $ so that $ X $ has a neighborhood base of open sets $ x $ with not more than $ alpha $ shows her limits.

Enter the image description here

The Sierpinski triangle has three order points $ 2 $Countable many order points $ 4 $ (the vertices of the other triangles) and all other points are in order $ 3 $,

The Sierpinski carpet has order $ mathfrak c = | mathbb R | $ at each of his points.

I'm looking for something between the Sierpinski triangle and the Sierpinski rug.

Question. Is there a fractal plane continuum that has order $ omega $ at each of his points?

Fractal can be loosely interpreted as "self-similar" or "simple recursive construction".

Is the function $ sinh (x) / x $ fractal at small values ​​of $ x, y $ or do I see rounding errors in the calculation?

I asked Wolfram Alpha to give me a solution for an integral function. Https://www.wolframalpha.com/input/?i=(integral+(expxmx)+dx)+ between + x-a + and + x% 2Ba +)% 2F (2onexp (-mx)))
and it gave me an expression that is equivalent
$ z = frac { sinh (xy)} {xy} $,

It also created a contour plot of the value of $ z $ for the domain $[-0.002, The surface z is not smooth, but has a complex (fractal?) Appearance.

If you use the formula $ z = sinh (x) / x $I calculated values ​​in Excel. I found a similar non-soft behavior for small values ​​of $ x: $ ($ 0 <x <$ 0.00002).

My question is: does $ z = sinh (x) / x $ have a fractal behavior for small values ​​of $ x $or is the irregularity (shown in Wolfram Alpha and Excel) due to rounding errors in the calculators?

Fractal – set with changed lower count dimension for the box, which is strictly below the Hausdorff dimension

Thank you for your response to MathOverflow!

  • Please be sure answer the question, Enter details and share your research!

But avoid

  • Ask for help, clarification or answering other answers.
  • Make statements based on opinions; secure them with references or personal experiences.

Use MathJax to format equations. Mathjax reference.

For more information, see our tips for writing great answers.

Fractal – Multifractal Package – Description of Multifractals

I'm trying to use this multifractal package, which is included in the classic book by Baumann – Mathematica for Theoretical Physics II. The problem is that the code is not working, that is, I have no charts. In my idea, this package could help with fractal modeling. Unfortunately it does not work. The problem is that I have not found a mistake. I reported the code below. Can you help me?

begin package["MultiFractal`"];
clear[Dq, Tau, Alpha, MultiFractal];
MultiFractal :: usage = "MultiFractal[p_List,r_List] calculates that
multifractal spectrum D_q for a model based on the probabilities
p and the scaling factors r. This feature records five functions
Tau (q), D_q (q), Alpha (q), f (q) and f (alpha). ";
begin["Private`"];
(* --- Calculate the multifractal dimensions --- *)
dq[p_List, r_List] : =
block[{l1, l2, listrg = {}},(*---length of the lists---*)
l1 = Length[p]; l2 = length[r];
If[l1 == l2,(*---variation of q and determination of D_q---*)
Do[gl1 = Sum[p[[j]]^ q r[[j]]^ ((q - 1) Dfractal), {j, 1, l1}]- 1;
Result = FindRoot[gl1 == 0, {Dfractal, -3, 3}];
Result = -Defractal /. Result;
(* --- collect the result in a list ---- *)
attach[listrg, {q, result}], {q, -10, 10, .101}], To press[" "];
To press["  Lengths of lists are different!"];
listrg = {}];
listrg];

(* ---- calculated dew --- *)
dew[result_list] : =
block[{l1, listtau = {}},(*----lengths of the lists---*)
l1 = Length[result];
(* --- calculate Tau --- *)
Do[AppendTo[
 listtau, {result[[k, 1]],
Result[[k, 2]](1 - result[[k, 1]])}], {k, 1, l1}];
listtau];

(* --- Legendre transformation --- *)
alpha[result_List] : =
block[{l1, dq, listalpha = {}, listf = {}, listleg = {}, mlist = {},
 pl1, pl2},(*---lengths of the lists---*)l1 = Length[result];
(* --- determine the differential dq --- *)
dq = (result[[2, 1]]- Result[[1, 1]]2;
(* --- calculate alpha by numerical differentiation --- *)
Do[AppendTo[
 listalpha, {result[[k, 
   1]](Result[[k + 1, 2]]- Result[[k - 1, 2]]) / dq}], {k, 2,
l1 - 1}];
l1 = length[listalpha];
(* --- compute f and put the result in a list --- *)
Do[AppendTo[
 listf, {result[[k, 
   1]], - (Result[[k, 1]]List Alpha[[k, 2]]- Result[[k, 2]])}];
List Alpha[[k, 2]]= -listalpha[[k, 2]], {k, 1, 12}];
(* --- List of Legendre Transformations --- *)
Do[Append[Listleg{listalpha[AppendTo[Listleg{listalpha[Anhängen[listleg{listalpha[AppendTo[listleg{listalpha[[k, 2]]listf[[k, 2]]}];
attach[mlistlistf[mlistlistf[mlistlistf[mlistlistf[[k, 2]]], {k, 1, l2}];
(* --- pl f and alpha against q --- *)
pl1 = ListLinePlot[listalpha, Joined -> {True, False}, 
 AxesLabel -> {"q", "[Alpha]"}, Prologue -> Thickness[0.001]];
pl2 = ListLinePlot[listf, Joined -> {True, False},
AxesLabel -> {"q", "f"}, Prologue -> Thickness[0.001]];
show[{pl1, pl2}, AxesLabel -> {"q", "[Alpha], f "}];
(* --- plot the Legendre transformation f against Alpha --- *)
ListLinePlot[listleg, AxesLabel -> {"[Alpha]"," f "}];
(* --- print the maximum of f = D_ 0 --- *) maxi = max[mlist];
To press[" "];
To press["   D_0 = ", maxi]];

(* --- Calculate the multifractal properties --- *)
Multifractal[p_List, r_List] : =
block[{listDq, listTau},(*---determine D_q---*)listDq = Dq[p, r];
ListLinePlot[listDq, Joined -> {True, False},
AxesLabel -> {"q", "Dq"}, Prologue -> Thickness[0.001]](* --- calculate Tau --- *) listTau = Tau[listDq];
ListLinePlot[listTau, Joined -> {True, False}, 
 AxesLabel -> {"q", "[Tau]"}, Prologue -> Thickness[0.001]](* --- Determine the hoarding exponent --- *) Alpha[listTau]];

The End[];

final packet[];

Analysis – How can I tell if a system correlates to a fractal?

So I'm studying the one-dimensional Abelian Sandpile for a research project. I mainly investigate if there is a relationship between this model and the Farey sequence.

I've flipped through some papers, mostly well above my level, but I came across a paper titled "Toppling Distributions in One-Dimensional Abelian Sandpiles" by P. Ruelle and S. Sen, stating that the one-dimensional case does not Show criticality. If someone could explain what that means, I would be very grateful.

Finally, I wanted to read the article by Levine, Pegden, and Smart, who relates the two-dimensional case of the Abelian Sandpile to the Apollonian Circles to gain further insights into the problem. However, it requires a background in PDEs. what I currently lack. Does anyone know if Evans's PDE book discusses this?

Which pattern type is generated by mod (x * y, w)? Is this an interference pattern, a simple fractal, or another pattern class?

When working with shaders I stumbled over this pattern several times. The visuals are very interesting – similar to moiré patterns, but more complicated.

I can not quite understand how it works, and I would like to know more about it, but I could not figure out what it is. Any information or tidbits about this pattern would be greatly appreciated.

Sample Example 1

Sample Example 2

Example 3

When applying a scale factor, this pattern has fractal-like properties, with each node appearing to be a smaller version of a similar pattern (but not infinite).

Sample example scaled

Here is a link to the shader where you can test the input parameters:
https://shaderfrog.com/app/view/2754