JavaFX: Mathematics & Physics
Fractals
A fractal can be implemented as a class that has a shape and consists of the same classes in JavaFX Script language
public abstract class Fractal {
public abstract function shape(): Node;
public abstract function childs(): Fractal[];
}
FractalView is a class that uses a recursion to show a fractal in the JavaFX Scene:
public class FractalView extends CustomNode {
public var fractal: Fractal;
public var depth: Integer;
override function create() {
create(depth, fractal);
}
function create(depth: Integer, fractal: Fractal): Node {
if (depth == 1) {
fractal.shape()
} else {
Group {
content: for (f in fractal.childs()) create(depth - 1, f)
}
}
}
}
Koch snowflake side is a fractal:
class Side extends Fractal {
public var x1: Number;
public var y1: Number;
public var x2: Number;
public var y2: Number;
override public function childs(): Fractal[] {
var dx = x2 - x1;
var dy = y2 - y1;
var x3 = x1 + dx / 3;
var y3 = y1 + dy / 3;
def sqrt = Math.sqrt(3.0);
var x4 = x1 + dx / 2 - sqrt * dy / 6;
var y4 = y1 + dy / 2 + sqrt * dx / 6;
var x5 = x1 + 2 * dx / 3;
var y5 = y1 + 2 * dy / 3;
[
Side { x1: x1 y1: y1 x2: x3 y2: y3 }
Side { x1: x3 y1: y3 x2: x4 y2: y4 }
Side { x1: x4 y1: y4 x2: x5 y2: y5 }
Side { x1: x5 y1: y5 x2: x2 y2: y2 }
]
}
override public function shape(): Node {
Line {
startX: x1 startY: y1 endX: x2 endY: y2
stroke: Color.BLUE
}
}
}
The Snowflake consistes of 3 sides:
class SnowFlake extends CustomNode {
public var centerX: Number;
public var centerY: Number;
public var radius: Number;
public var depth: Integer;
override function create() {
def angle = 2 * Math.PI / 3;
def PI2 = Math.PI / 2;
var x = for (i in [1..3]) centerX + radius * Math.cos(i * angle + PI2);
var y = for (i in [1..3]) centerY - radius * Math.sin(i * angle + PI2);
Group {
content: [
FractalView {
depth: depth
fractal: Side { x1: x[0] y1: y[0] x2: x[1] y2: y[1] }
}
FractalView {
depth: depth
fractal: Side { x1: x[1] y1: y[1] x2: x[2] y2: y[2] }
}
FractalView {
depth: depth
fractal: Side { x1: x[2] y1: y[2] x2: x[0] y2: y[0] }
}
]
}
}
}
And the main application is
Stage {
title: "Snowflake"
scene: Scene {
width: 400
height: 400
content: SnowFlake {
depth: 6
centerX: 200
centerY: 200
radius: 150
}
}
}
Posted at 06:59PM Jan 15, 2010 by Alexandr Scherbatiy in Sun | Comments[0]
JavaFX Set Demo
JavaFX Set is the open-source project that contains a set of JavaFX samples.
From the lists on the left side you can choose to work with Shapes, Transforms, Controls, Animation, Media and simple samples.
See the JavaFX Set Demo
Anyone can add his samples to the JavaFX Set project using the steps below:
- Checkout the JavaFX Set project from the repository
- > svn checkout https://svn.kenai.com/svn/javafxset~master javafxset
- Open the project in an IDE with JavaFX plugin
- Add you sample under the javafxset.samples package
- Open the javafxset.samples.Configuration.fx file
- Add the Sample record to the Module class
- Commit the changes
import javafxset.core.Module;
import javafxset.core.Sample;
Module {
name: "Samples"
samples: [
Sample{
name: "Hello World"
className: "javafxset.samples.FXHelloWorld"
},
Sample{
name: "Sample Name"
className: "javafxset.samples.SampleFile"
},
]
}
Posted at 06:37PM Nov 17, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Simple Graph Sample
This is the simple Graph sample written on JavaFX Script language.
The graph consists of edges and vertices. The Connection class is used for the graph creation.
The GraphView is a Node for painting the graph object .
Stage {
title : "JavaFX Simple Graph"
scene: Scene {
width: 300
height: 300
content: [
GraphView{
translateX: 150
translateY: 150
graph: Graph{
order: 5
connections: [
Connection{ vertex1: 0 vertex2: 1 }
Connection{ vertex1: 0 vertex2: 2 }
Connection{ vertex1: 0 vertex2: 3 }
Connection{ vertex1: 1 vertex2: 2 }
Connection{ vertex1: 3 vertex2: 4 }
]
}
}
]
}
}
Below is the source code of the Graph class.The full source code is integrated into the open source JavaFX MultiDimensional Library project.
public class Edge {
public var vertex1:Vertex;
public var vertex2:Vertex;
}
public class Vertex {
public var edges:Edge[];
}
public class Connection {
public var edge:Edge;
public var vertex1:Integer;
public var vertex2:Integer;
}
public class Graph {
public var order:Integer;
public var vertices:Vertex[];
public var edges: Edge[];
public var connections:Connection[];
init{
for(i in [sizeof vertices..order-1]){
insert Vertex{} into vertices;
}
order = sizeof vertices;
for(connection in connections){
var edge = connection.edge;
if(edge == null){ edge = Edge{}; }
insert edge into edges;
var v1 = vertices[connection.vertex1];
var v2 = vertices[connection.vertex2];
edge.vertex1 = v1;
edge.vertex2 = v2;
insert edge into v1.edges;
insert edge into v2.edges;
}
}
}
Posted at 03:10PM Oct 01, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
NumberBox control
It is not so difficult to create a NumberBox control using the Textbox control, triggers and data binding in JavaFX:
import javafx.scene.*;
import javafx.scene.control.*;
public class NumberBox extends CustomNode {
public var value:Number on replace { str = "{value}"};
var str:String on replace{
try{
value = Number.valueOf(str);
} catch(e){
str = "0";
}
}
public override function create(): Node {
TextBox {
columns: 12
selectOnFocus: true
text: bind str with inverse
}
}
}
Example with the NumberBox control:
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.layout.*;
import javafx.scene.control.*;
var num = 10.0;
Stage {
title: "NumberBox"
width: 250
height: 280
scene: Scene {
content: VBox{
translateX: 20
translateY: 20
content: [
Slider {
min: 0
max: 100
value: bind num with inverse
}
NumberBox{
value: bind num with inverse
}
]
}
}
}
Posted at 01:55PM Sep 23, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Permutation Algorithm
The algorithm below just permutes i and j elements of a sequence to produce a list of all permutations:
function permutation(arr:Integer[]):Void{
permutation(0, sizeof arr, arr)
}
function permutation(index: Integer, size:Integer, arr:Integer[]):Void{
if(index == size-1){ println(arr); return; }
permutation(index+1, size, arr);
for(i in [index+1..size-1]){
permutation( index+1, size, [ arr[0..index-1], arr[i],arr[index+1..i-1],arr[index],arr[i+1..size-1]]);
}
}
For example:
permutation([1..4]);produces:
[ 1, 2, 3, 4 ] [ 1, 2, 4, 3 ] [ 1, 3, 2, 4 ] [ 1, 3, 4, 2 ] [ 1, 4, 3, 2 ] [ 1, 4, 2, 3 ] [ 2, 1, 3, 4 ] [ 2, 1, 4, 3 ] [ 2, 3, 1, 4 ] [ 2, 3, 4, 1 ] [ 2, 4, 3, 1 ] [ 2, 4, 1, 3 ] [ 3, 2, 1, 4 ] [ 3, 2, 4, 1 ] [ 3, 1, 2, 4 ] [ 3, 1, 4, 2 ] [ 3, 4, 1, 2 ] [ 3, 4, 2, 1 ] [ 4, 2, 3, 1 ] [ 4, 2, 1, 3 ] [ 4, 3, 2, 1 ] [ 4, 3, 1, 2 ] [ 4, 1, 3, 2 ] [ 4, 1, 2, 3 ]
Posted at 04:13PM Jul 17, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Bubble Sort Algorithm
Bubble sort algorithm written on JavaFX Script:
function bubbleSort(seq:Number[]):Number[]{
var sort = seq;
var elem:Number;
for(n in reverse [0..sizeof seq - 2]){
for(i in [0..n] ){
if(sort[i+1] < sort[i] ){
elem = sort[i];
sort[i] = sort[i+1];
sort[i+1] = elem;
}
}
}
return sort;
}
For example:
println( bubbleSort( [5,3,1,2,4] ) ); // output: [ 1.0, 2.0, 3.0, 4.0, 5.0 ]
Posted at 04:23PM Jul 15, 2009 by Alexandr Scherbatiy in Sun | Comments[2]
Hyper Cube
There are a lot of interesting 3, 4 or even more dimensional shapes that can be created with the MultiDimensional library on JavaFX Script.
Take a look at the Hyper Cube sample code. It can be included into any JavaFX application.
import javafx.stage.*;
import javafx.scene.*;
import javafx.animation.*;
import javafx.scene.transform.*;
import mathematics.multidimensional.*;
import mathematics.multidimensional.shape.*;
var dim = 4;
Stage {
title: "Hyper Cube"
width: 300
height: 300
scene: Scene{
content: MDUniversePlayer{
transforms: Transform.translate(150,140);
dimension: dim
time: 30s
autoplay: true
shapes: [ MDCube{ dim: dim side: 50} ]
}
}
}
Posted at 05:14PM Jun 06, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Functorial and Gamma functions
The factorial function is defined by:
- `n! = 1 * 2 * ... * n`
or recursively defined by:
- `n! = 1 if n=0 `
- `n! = n * (n-1)! if n>0`
function factorial(n:Integer):Integer{
if (n==0) 1 else n * factorial(n-1)
}
The Gamma function is defined by:
`\Gamma(z) = \int_0^\infty t^{z-1} e^{-t}\,dt `
It is related to the factorial by:
`Gamma(n) = (n-1)!`
The implementation of the Gamma function in JavaFX is:
def dx = 0.1;
def INFINITY = 1e5;
function gamma(a:Number):Number{
integral(function (x: Number):Number{
Math.pow(x, a - 1) * Math.exp( - x);
}, 0, INFINITY, dx);
}
function integral(f:function(Number):Number, a:Number, b:Number, dx):Number{
var s = 0.0;
var x = a;
while(x <= b){ x += dx; s += f(x) * dx; }
return s;
}
Let's compare the factorial and the Gamma functions:
for(n in [1..7]){
println("n = {n}");
println("factorial({n }) = {factorial(n)}");
println("gamma ({n+1}) = {gamma(n + 1)}");
println("");
}
n = 1 factorial(1) = 1 gamma (2) = 0.9991672 n = 2 factorial(2) = 2 gamma (3) = 1.9999995 n = 3 factorial(3) = 6 gamma (4) = 6.0000014 n = 4 factorial(4) = 24 gamma (5) = 24.000011 n = 5 factorial(5) = 120 gamma (6) = 119.999954 n = 6 factorial(6) = 720 gamma (7) = 719.99945 n = 7 factorial(7) = 5040 gamma (8) = 5039.9897
Posted at 07:57PM May 30, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Sequences: sum and mul functions
I asked a question about sum and mul functions for sequences in JavaFX on JavaFX forum
and PhiLho replayed that it is possible to implement such functions using the suggested reduce function:
function reduce(sequence: Number[], s:Number, operator: function (r: Number, v: Number): Number): Number{
var result = s;
for (v in sequence){
result = operator(result, v);
}
return result;
}
function sum(seq:Number[]):Number{ reduce(seq, 0, function (r:Number, v:Number) { r + v }) }
function mul(seq:Number[]):Number{ reduce(seq, 1, function (r:Number, v:Number) { r * v }) }
var seq = [ 1, 2, 3, 4, 5];
println("sum: {sum(seq)}");
println("mul: {mul(seq)}");
The results for the [ 1, 2, 3, 4, 5] sequence are:- sum: 15.0
- mul: 120.0
Posted at 02:05PM May 20, 2009 by Alexandr Scherbatiy in Sun | Comments[1]
Matrix-Vector Multiplication
Assume that `x` and `y` are vectors and `A` is a matrix.
The matrix-vector multiplication is defined as:
`y=Ax`
`y_n=sum_m A_{n,m} y_m`
JavaFX does not contains arrays. It contains sequences which have only one dimension.
To create a matrix class we will use getElem method:
function getElem (n:Integer, m: Integer):Number {
return elems[dimM * n + m ];
}
Using the getElem function allows to program a matrix-vector multiplication in JavaFX:
function sum(nums:Number[]):Number{
var s = 0.0;
for(num in nums) s+=num;
return s;
}
public class Vector {
public var dim: Integer ;
public var elems: Number[];
public function getElem(n: Integer):Number{ elems[n] }
override function toString ():String { "[ {for(s in elems) (" {s}")} ]" }
}
public class Matrix {
public var dimN:Integer;
public var dimM:Integer;
public var elems:Number[] ;
function getElem (n:Integer, m: Integer):Number {
return elems[dimM * n + m ];
}
public function mul (vector:Vector):Vector {
Vector{
dim: dimN
elems: for(n in [0..dimN -1]) sum(for(m in [0..dimM-1]) getElem ( n, m ) * vector.getElem(m))
}
}
}
Let's try to calculate something:
var vector = Vector{
dim: 2
elems: [ 1, 2 ]
}
var matrix = Matrix{
dimN: 2
dimM: 2
elems: [
[ 1, 2 ],
[ 3, 4 ]
]
}
println("result: {matrix.mul(vector)}");
The result is: [ 5.0 11.0 ]
Posted at 12:43PM May 18, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Planetary System
The program below uses Newton's laws of motion for the Solar system modeling:
Physical Object:
public class PhysicalObject {
public var name: String;
public var mass: Number;
public var radius: Number;
public var color: Color;
public var coordinate: VectorDim3 = VectorDim3{};
public var velocity: VectorDim3 = VectorDim3{};
public var acceleration: VectorDim3 = VectorDim3{};
}
Physical Object System:
public class PhysicalObjectSystem{
public var dt: Number = 60* 60 * 24 * 2;
public var G: Number = 6.67e-11;
public var objects: PhysicalObject[];
public function run():Void{
for(obj1 in objects){
obj1.acceleration.zero();
for(obj2 in objects[obj| obj!= obj1]){
var distance = obj2.coordinate.sub(obj1.coordinate);
obj1.acceleration = obj1.acceleration.add(distance.normal().mul(G * obj2.mass / distance.square() ))
}
}
for(obj in objects){
obj.velocity = obj.velocity.add( obj.acceleration.mul( dt) );
obj.coordinate = obj.coordinate.add( obj.velocity.mul( dt ));
}
}
}
System Visualization:
public class PhysicalObjectSystem extends CustomNode{
override function create():Node{
Group{
content: bind for(obj in objects)
Group{
content: [
Circle{
centerX: bind obj.coordinate.elems[0] * scale.coordinateScale
centerY: bind obj.coordinate.elems[1] * scale.coordinateScale
radius: obj.radius * scale.radiusScale
fill: obj.color
},
Text{
content: obj.name
font: Font {name: "BOLD" size: 16}
x: bind obj.coordinate.elems[0] * scale.coordinateScale + 15
y: bind obj.coordinate.elems[1] * scale.coordinateScale - 15
strokeWidth: 3
fill: Color.WHITE
}
]
}
};
}
}
Main program:
var solarSystem = PhysicalObjectSystem{
objects: [
PhysicalObject{
name: "Sun"
mass : 2e30
color: Color.YELLOW
radius: 14000
coordinate : VectorDim3{}
velocity : VectorDim3{}
},PhysicalObject{
name: "Mercury"
mass : 3.3e23
color: Color.BLUE
radius: 2400
coordinate : VectorDim3{ elems:[ -57e9 , 0, 0] }
velocity : VectorDim3{ elems: [ 0, -47e3, 0 ] }
},
PhysicalObject{
name: "Venus"
mass : 4.8e24
color: Color.PINK
radius: 6000
coordinate : VectorDim3{ elems: [ 108e9 , 0, 0] }
velocity : VectorDim3{ elems: [ 0, 35e3, 0 ] }
},
PhysicalObject{
name: "Earth"
mass : 6e24
color: Color.GREEN
radius: 6300
coordinate : VectorDim3{ elems: [ 0 , -150e9, 0 ] }
velocity : VectorDim3{ elems: [ 30e3, 0, 0 ] }
},PhysicalObject{
name: "Mars"
mass : 6.4e23
color: Color.RED
radius: 3400
coordinate : VectorDim3{ elems: [ 0 , 228e9, 0 ] }
velocity : VectorDim3{ elems: [ -24e3, 0, 0 ] }
}
]
};
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: KeyFrame {
time: 0.02s
action: function() { solarSystem.run(); }
}
}.play();
var w = 600;
var h = 400;
Stage {
title: "Solar System"
width: w
height: h
scene: Scene{
content: Group{
transforms: Transform.translate(w/2, h/2)
content: [ Stars{}, solarSystem ]
}
fill: Color.BLACK
}
}
Posted at 05:17PM May 15, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Pendulum
A simple pendulum consists of a ball of mass m tied to a string which is considered massless.
In order to realize Newton's second law you need to project the force mg on a line perpendicular to the string:
- m (length * amplitute)'' = mg * sin(amplitute)
Here is a small JavaFX code snippet that allows you to simulate a pendulum:
def g = 9.8;
def dt = 0.1;
public class Pendulum {
public var length: Number;
public var mass: Number;
public var amplitute: Number;
public var velocity:Number;
public var acceleration:Number;
public function run(){
acceleration = - g / length * Math.sin(amplitute);
velocity += acceleration * dt;
amplitute += velocity * dt;
}
}
Full source code
Pendulum.fx
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import java.lang.Math;
def g = 9.8;
def dt = 0.1;
public class Pendulum extends CustomNode {
public var length: Number;
public var mass: Number;
public var amplitute: Number;
public var velocity:Number;
public var acceleration:Number;
public function run(){
acceleration = - g / length * Math.sin(amplitute);
velocity += acceleration * dt;
amplitute += velocity * dt;
}
public override function create(){
Group{
content: [
Line {
endX: bind length * Math.sin(amplitute)
endY: bind length * Math.cos(amplitute)
stroke: Color.ORANGE
},
Circle {
radius: 5
fill: Color.GRAY
},
Circle {
centerX: bind length * Math.sin(amplitute)
centerY: bind length * Math.cos(amplitute)
radius: 20
fill: Color.YELLOW
stroke: Color.ORANGE
}
]
}
}
}
Main.fx
import javafx.stage.*;
import javafx.scene.*;
import javafx.animation.*;
import java.lang.Math;
var pendulum = Pendulum{
mass: 10
length: 150
amplitute: Math.PI / 4
};
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 10ms
canSkip : true
action: function(){
pendulum.run();
}
}
]
}.play();
Stage {
title: "Pendulum"
width: 300
height: 300
scene: Scene {
content: [
Group{
translateX: 150 translateY: 30
content: pendulum
}
]
}
}
Click on the Pendulum to run it as an applet.
Posted at 02:56PM Apr 27, 2009 by Alexandr Scherbatiy in Sun | Comments[4]
Numerical Integration
Here is an implementation of the rectangle method for integrals calculation on JavaFX Script language:
function integral(f:function(Number):Number, a:Number, b:Number, dx:Number):Number{
var s = 0.0;
var x = a;
while(x <= b){
x += dx;
s += f(x) * dx;
}
return s;
}
Let's calculate an integral of cos(x) function:
import java.lang.Math;
function cos(x:Number):Number{ Math.cos(x) }
println( integral(cos, -Math .PI / 2, Math.PI / 2, 0.01) );
The result is: 1.9999075
Posted at 06:08PM Apr 15, 2009 by Alexandr Scherbatiy in Sun | Comments[0]
Simple Function Plotter
It is very simple to show a function graphic using JavaFX Script language. What you need is a simple JavaFX component that draws a function point by point:
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
public class FunctionView extends CustomNode{
public var xMin: Number;
public var xMax: Number;
public var dx: Number = 0.1;
public var scale: Number = 1.0;
public var color: Color = Color.BLUE;
public var func: function(a: Number):Number;
override function create():Node{
Polyline{
stroke: color
points: for(x in [xMin..xMax step dx]) [x * scale, func(x) * scale]
}
}
}
To use it in the JavaFX Script program, just put the FunctionView component into the Stage:
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.transform.*;
import java.lang.Math;
function f(x:Number):Number{ 10 * Math.sin(3 * x) / (1 + x * x) }
Stage {
title: "Function Graphic"
scene: Scene {
width: 200
height: 200
content: Group {
transforms: [ Translate{ x: 100 y: 100}, Scale{ x: 1 y: -1 } ]
content: FunctionView{
xMin: -10
xMax: 10
scale: 10
func: f
}
}
}
}
Put the code into the FunctionView.fx and Main.fx files and run the Main file.
Posted at 03:19PM Apr 12, 2009 by Alexandr Scherbatiy in Sun | Comments[3]