animation
截图:
布朗树是一种分形结构,和雪花类似。
原理:
粒子做随机运动,设置一个种子进入固定状态。
当其它粒子运动到已固定的粒子的附近时,也被固定住。
代码
public class BrownTree extends Application{
Pane pane=new Pane();
public static void main(String[] args) {launch();}
public BrownTree() {
}
public void addParticle(Pane pane) {
for(int i=0;i<3000;i++) {
Particle p=new Particle(Particle.MIN+Math.random()*600,Particle.MIN+Math.random()*600);
pane.getChildren().add(p.getNode());
}
Particle center=new Particle(300,300);
pane.getChildren().add(center.getNode());
center.goDie();
}
public void start(Stage primaryStage) throws Exception {
addParticle(pane);
ParticleService service=new ParticleService();
service.setDelay(Duration.seconds(1));
service.setPeriod(Duration.seconds(0.1));
service.start();
pane.setOnMouseClicked(e->{
service.cancel();
});
primaryStage.setScene(new Scene(pane));
primaryStage.setWidth(600);
primaryStage.setHeight(600);
primaryStage.setTitle("布朗树 ");
primaryStage.show();
}
}
class ParticleService extends ScheduledService<Number>{
protected Task<Number> createTask() {
Task<Number> task=new Task<Number>(){
protected void updateValue(Number value) {
super.updateValue(value);
Particle.list.forEach(Particle::move);
}
protected Number call() throws Exception {
return null;
}
};
return task;
}
}
class Particle{
static ArrayList<Particle> list=new ArrayList<Particle>();
final static int SIZE=2;
final static int MIN=0;
final static int MAX=600;
final int SPACE=10;
boolean live=true;
public Circle node;
public Particle(double x ,double y) {
node=new Circle(x,y,SIZE);
node.setFill(Color.valueOf("#43CD80"));
list.add(this);
}
public Circle getNode() {
return node;
}
public void move() {
if(this.live) {
double x=0;
double y=0;
do{
x=node.getCenterX()+(Math.random()>0.5?1:-1)*Math.random()*SPACE;
y=node.getCenterY()+(Math.random()>0.5?1:-1)*Math.random()*SPACE;
}while(x<MIN||x>MAX||y<MIN||y>MAX) ;
node.setCenterX(x);
node.setCenterY(y);
for(Particle itme:list) {
if(this!=itme&&isNear(this,itme)&&itme.live==false) {
goDie();
}
}
}
}
public void goDie() {
node.setFill(Color.valueOf("#912CEE"));
this.live=false;
}
public static boolean isNear(Particle u,Particle r) {
double x = u.node.getCenterX()-r.node.getCenterX();
double y= u.node.getCenterY()-r.node.getCenterY();
return x*x+y*y<64;
//return x*x+y*y<Math.pow((u.getNode().getRadius()+r.getNode().getRadius()),2);
}
}