Graph Generator

Discuss scenes and videos made with Algodoo.

Graph Generator

Postby KarateBrot » Mon Nov 09, 2009 5:30 pm

Rating: rated 8.2
Filesize: 29 kB
Comments: 14
Ratings: 13
download


Image
Update v1.1: Improved algorithm to approximate roots

Note:
I soon will make a new version which also includes the
antiderivative and the area under the function.

With this scene you can visualize mathematical functions. Next to "f(x) =" just type any function you want into the text box (make sure to use normal formatting like in the examples below). After that you can draw the graph, show it's roots, draw the first or second derivative.
As an example I already entered a function to the text box.

How to:
  1. Start the simulation (press SPACE)
  2. Select the text box next to "f(x) =" and go to it's appearance menu.
  3. Now change the box text. Type in your desired function (or just keep the example function)
  4. Close the appearance menu. Navigate with the ARROW KEYS within the menu. Choose with ENTER

Controls:
Arrows - Navigate
Enter - Choose
D - delete graph

Function types: (examples)
  • 2*x -3
  • x^5 - 2*x^4 - 3*x^3 + 2*x^2 + x - 0.25
  • 1/math.sin(x)
  • math.cos(x) -x
  • 3^x -1
  • math.tan(x)
  • math.sin(math.cos(x))
  • x^2 - 2^x
  • x^0.5
Because Algodoo has no implemented ln I made my own ln. To use it type "scene.my.ln()"
  • scene.my.ln(x^2 +1)

Known bugs:
The 2. derivative of scene.my.ln() is very imprecise due to the limited precision Algodoo calculates with

Scripting code:
If you're interested in the scripting code here it is
Code: Select all
Scene.my.derive2 := (f, x)=>{(scene.my.derive(f, x + 0.01) - scene.my.derive(f, x)) / 0.01};
Scene.my.ArraySize := (array)=>{
    a := array ++ ["end"];
    n := 0;
    SizeUnknown := true;
    for(20, (i)=>{
        SizeUnknown ? {
            math.toString(a(i)) == "end" ? {
                n = i;
                SizeUnknown = false
            } : {}
        } : {}
    });
    n
};
Scene.my.graph_derive := (f)=>{
    scene.my.for2(100, (i)=>{
        scene.my.derive(f, (i / 10.0 - 5)) >= (-5.1) && scene.my.derive(f, (i / 10.0 + 0.1 - 5)) >= (-5.1) ? {
            scene.my.derive(f, (i / 10.0 - 5)) <= 5.1 && scene.my.derive(f, (i / 10.0 + 0.1 - 5)) <= 5.1 ? {
                scene.addcircle({
                    radius := 0.01;
                    color := [0.33, 1, 0.33, 1];
                    drawborder := false;
                    drawcake := false;
                    buttondestroy := "d";
                    body := 0;
                    pos := [i / 10.0 - 5, scene.my.derive(f, (i / 10.0 - 5))]
                });
                scene.addbox({
                    color := [0.33, 1, 0.33, 1];
                    drawborder := false;
                    buttondestroy := "d";
                    body := 0;
                    size := [(0.1 ^ 2 + (scene.my.derive(f, (i / 10.0 + 0.1 - 5)) - scene.my.derive(f, (i / 10.0 - 5))) ^ 2) ^ 0.5, 0.02];
                    angle := math.atan((scene.my.derive(f, (i / 10.0 + 0.1 - 5)) - scene.my.derive(f, (i / 10.0 - 5))) / 0.1);
                    pos := [i / 10.0 + 0.05 - 5, (scene.my.derive(f, (i / 10.0 + 0.1 - 5)) + scene.my.derive(f, (i / 10.0 - 5))) / 2]
                })
            } : {}
        } : {}
    })
};
Scene.my.iteration := (f, x)=>{
    z := math.tofloat(x);
    zM := 10;
    for(30, (i)=>{
        zM == z ? {} : {
            zM = z;
            z = z - f(z) / scene.my.derive(f, z)
        }
    });
    scene.my.abs(zM - z) < 0.01 ? {
        scene.my.nullcheck = true;
        z
    } : {scene.my.nullcheck = false}
};
Scene.my.null := (f)=>{
    nulls := [];
    scene.my.for2(31, (i)=>{
        x0 := scene.my.iteration(f, (i - 15) / 3.0);
        scene.my.nullcheck ? {scene.my.IsInArray(x0, nulls) ? {} : {nulls = nulls ++ [x0]}} : {}
    });
    Scene.my.ArraySize(nulls) > 0 ? {
        for(Scene.my.ArraySize(nulls), (i)=>{
            scene.my.abs(nulls(i)) <= 5 ? {
                scene.addbox({
                    size := [0.03125, 0.1875];
                    angle := math.pi / 4;
                    color := [1, 1, 1, 1.0];
                    drawBorder := false;
                    body := 0;
                    buttondestroy := "d";
                    pos := [nulls(i), 0]
                });
                scene.addbox({
                    size := [0.03125, 0.1875];
                    angle := 3 * math.pi / 4;
                    color := [1, 1, 1, 1.0];
                    drawBorder := false;
                    body := 0;
                    buttondestroy := "d";
                    pos := [nulls(i), 0]
                });
                scene.addbox({
                    size := [1.5, 0.25];
                    color := [1, 1, 1, 0.0];
                    drawBorder := false;
                    body := 0;
                    buttondestroy := "d";
                    text := "" + (nulls(i) - nulls(i) % 1e-008);
                    textScale := 0.23;
                    pos := [nulls(i) + 0.5, 0.25]
                })
            } : {}
        })
    } : {}
};
Scene.my.graph := (f)=>{
    scene.my.for2(100, (i)=>{
        f(i / 10.0 - 5) >= (-5.1) && f(i / 10.0 + 0.1 - 5) >= (-5.1) ? {
            f(i / 10.0 - 5) <= 5.1 && f(i / 10.0 + 0.1 - 5) <= 5.1 ? {
                scene.addcircle({
                    radius := 0.01;
                    color := [1, 0, 0, 1];
                    drawborder := false;
                    drawcake := false;
                    buttondestroy := "d";
                    body := 0;
                    pos := [i / 10.0 - 5, f(i / 10.0 - 5)]
                });
                scene.addbox({
                    color := [1, 0, 0, 1];
                    drawborder := false;
                    buttondestroy := "d";
                    body := 0;
                    size := [(0.1 ^ 2 + (f(i / 10.0 + 0.1 - 5) - f(i / 10.0 - 5)) ^ 2) ^ 0.5, 0.02];
                    angle := math.atan((f(i / 10.0 + 0.1 - 5) - f(i / 10.0 - 5)) / 0.1);
                    pos := [i / 10.0 + 0.05 - 5, (f(i / 10.0 + 0.1 - 5) + f(i / 10.0 - 5)) / 2]
                })
            } : {}
        } : {}
    })
};
Scene.my.abs := (x)=>{x < 0 ? {x * (-1)} : {x}};
Scene.my.derive := (f, x)=>{(f(x + 0.01) - f(x)) / 0.01};
Scene.my.ln := (x)=>{(x ^ 0.01 - 1) / 0.01};
Scene.my.select := [1, 1];
Scene.my.for2_internal := (n, min, max, what)=>{
    (min == max) ? {(min < n) ? {what(min)} : {}} : {
        Scene.my.for2_internal(n, min, min + (max - min + 1) / 2 - 1, what);
        Scene.my.for2_internal(n, min + (max - min + 1) / 2, max, what)
    }
};
Scene.my.for2 := (n, what)=>{
    num := Math.toFloat(Math.toInt(n));
    max := 2 ^ (Math.toInt(((num ^ 0.001 - 1) / (2 ^ 0.001 - 1)) + 1));
    (num <= 0) ? {} : {
        (num == 1) ? {what(0)} : {
            Scene.my.for2_internal(num, 0, (max / 2) - 1, what);
            Scene.my.for2_internal(num, (max / 2), max - 1, what)
        }
    }
};
Scene.my.graph_derive2 := (f)=>{
    scene.my.for2(100, (i)=>{
        scene.my.derive2(f, (i / 10.0 - 5)) >= (-5.1) && scene.my.derive2(f, (i / 10.0 + 0.1 - 5)) >= (-5.1) ? {
            scene.my.derive2(f, (i / 10.0 - 5)) <= 5.1 && scene.my.derive2(f, (i / 10.0 + 0.1 - 5)) <= 5.1 ? {
                scene.addcircle({
                    radius := 0.01;
                    color := [0.75, 1, 0.75, 1];
                    drawborder := false;
                    drawcake := false;
                    buttondestroy := "d";
                    body := 0;
                    pos := [i / 10.0 - 5, scene.my.derive2(f, (i / 10.0 - 5))]
                });
                scene.addbox({
                    color := [0.75, 1, 0.75, 1];
                    drawborder := false;
                    buttondestroy := "d";
                    body := 0;
                    size := [(0.1 ^ 2 + (scene.my.derive2(f, (i / 10.0 + 0.1 - 5)) - scene.my.derive2(f, (i / 10.0 - 5))) ^ 2) ^ 0.5, 0.02];
                    angle := math.atan((scene.my.derive2(f, (i / 10.0 + 0.1 - 5)) - scene.my.derive2(f, (i / 10.0 - 5))) / 0.1);
                    pos := [i / 10.0 + 0.05 - 5, (scene.my.derive2(f, (i / 10.0 + 0.1 - 5)) + scene.my.derive2(f, (i / 10.0 - 5))) / 2]
                })
            } : {}
        } : {}
    })
};
Scene.my.nullcheck := true;
Scene.my.IsInArray := (n, array)=>{
    IsIn := false;
    for(scene.my.ArraySize(array), (i)=>{scene.my.abs(array(i) - n) <= 0.1 ? {IsIn = true} : {}});
    IsIn
};


Credits:
Thanks to gradyfitz and standardtoaster for having an answer to scripting questions all the time related to this scene and to immibis for his extended for-function.
Last edited by KarateBrot on Mon Dec 21, 2009 12:46 am, edited 3 times in total.
Image
User avatar
KarateBrot
 
Posts: 825
Joined: Mon Aug 31, 2009 7:32 pm
Location: Germany

Re: Graph Generator

Postby niffirg1 » Tue Nov 10, 2009 12:29 am

Dude this is awesome
User avatar
niffirg1
 
Posts: 376
Joined: Mon Aug 31, 2009 10:31 pm
Location: The Great American South!

Re: Graph Generator

Postby Conundrumer » Tue Nov 10, 2009 3:56 am

This is really good. Looking at the code makes me feel like I'm looking into some real pro computer programing.

Consider making a curved polygon generator with something like this. Also, consider polar coordinates and parametric equations. Oh yes, integrals too.
This reminds me I should get that differential analyzer done.
User avatar
Conundrumer
 
Posts: 344
Joined: Mon Aug 31, 2009 5:55 pm
Location: NYC

Re: Graph Generator

Postby Kilinich » Tue Nov 10, 2009 2:07 pm

Wellcome to phun/algodoo crazy :crazy: scripters team :D
Dream of Algodoo as game development engine...
User avatar
Kilinich
[Best bug reporter 2010]
 
Posts: 2098
Joined: Mon Aug 31, 2009 8:27 pm
Location: South Russia

Re: Graph Generator

Postby KarateBrot » Thu Nov 12, 2009 7:23 pm

Kilinich wrote:Wellcome to phun/algodoo crazy :crazy: scripters team :D


:D it wasn't intended to be so much scripting but i just did this and that, got some ideas while working on it and the code was getting longer and longer and yeah... that's what i came up with :D
the idea came to my mind while i was working on maths functions and i wanted to check if everything was typed in correctly so i spawned a few circles with the function coordinates to see the curve. then i built everything up based on this idea.
Image
User avatar
KarateBrot
 
Posts: 825
Joined: Mon Aug 31, 2009 7:32 pm
Location: Germany

Re: Graph Generator

Postby Antotabo » Fri Nov 13, 2009 12:22 am

WOW! this is really cool ! you made such a great job. :thumbup:

I made a very basic one out of springs, rails and tracer drawing the curve while moving. but that had nothing to do with this complex thing with derivatives...
Antotabo
 
Posts: 54
Joined: Tue Sep 01, 2009 6:27 am


Return to Scenes

Who is online

Users browsing this forum: No registered users and 3 guests

cron