RelativityParticleCollision
Материал из JavaFX
Главная | Описание языка | API | Примеры | Инструменты Разработки | Новости | Ресурсы | Вопросы и ответы | Форум
[править] Разлет частиц
[править] Релятивистский случай
Столкновение частиц.
Закон сохранения импульса и энергии:
import javafx.animation.*;
import javafx.application.*;
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.geometry.*;
import javafx.scene.transform.*;
import java.lang.Math;
import java.lang.System;
var a = 2;
var i=0;//счетчик
var v = 0.887;//скорость налетающей частицы относительно скорости света
var m1=10;//масса первой частицы
var m2=10;//масса второй частицы
var ang = Math.random()*Math.PI;//угол разлета в системе центра масс
if (ang==0) ang=Math.PI;//частицы не могут пройти сквозь друг друга
function abs (x:Number):Number {
return if ( 0 < x ) then x else -x;
}
function q (w:Number):Number{//возведение в квадрат
return w*w
}
function arth (x:Number):Number{//обратная к гиперболическому тангенсу
return Math.log((1+x)/(1-x))/2
}
function arch (x:Number):Number{//~косинуа
return Math.log(x+Math.sqrt(q(x)-1))
}
function arsh (x:Number):Number{//~синуса
return Math.log(x+Math.sqrt(q(x)+1))
}
function tch (ang:Number, v1:Number, v2:Number):Number{//по теореме косинусов находит сторону по сторонам и углу
return if (ang==Math.PI) v1+v2
else if (ang==0) v1-v2
else arch(Math.cosh(v1)*Math.cosh(v2)-Math.sinh(v1)*Math.sinh(v2)*Math.cos(ang));
}
function tch1 (v1:Number, v2:Number, v3:Number):Number{//по теореме косинусов находим угол разлета
return if (v2==0) 0
else Math.acos((Math.cosh(v1)*Math.cosh(v2)-Math.cosh(v3))/Math.sinh(v1)/Math.sinh(v2))
}
function d (p1:Particle,p2:Particle){//обработка события столкновения
var v1=arth(p2.mass*Math.sinh(arth(v))/(p1.mass+p2.mass*Math.cosh(arth(v))));//расстояние по кинематическому графу
var v2=arth(p1.mass*Math.sinh(arth(v))/(p2.mass+p1.mass*Math.cosh(arth(v))));//расстояние по кинематическому графу
var ang1=tch1(v2, tch(Math.PI-ang, v1,v2),v1);//угол отлета первой частицы
var ang2=tch1(v2,tch(ang,v2,v2),v2);//угол отлета второй частицы
p1.dX=Math.cos(ang1)*Math.tanh(tch(Math.PI-ang,v1,v2))*10/v;//нахолим скорость по оси абсцисс
p1.dY=-Math.sin(ang1)*Math.tanh(tch(Math.PI-ang,v1,v2))*10/v;//и ординат
p2.dX=Math.cos(ang2)*Math.tanh(tch(ang,v2,v2))*10/v;
p2.dY=Math.sin(ang2)*Math.tanh(tch(ang,v2,v2))*10/v;
}
public class Particle{//класс частиц
public attribute name:String ;
public attribute color:Color;
public attribute x:Number ;
public attribute y:Number ;
public attribute dX:Number ;
public attribute dY:Number ;
public attribute radius:Number ;
public attribute mass:Number;
}
public class ParticleSystem extends CustomNode{//сама модель
public attribute particles: Particle[];
public attribute dt:Number = 0.05 ;
public function run () {
for (particle1 in particles){
for (particle2 in particles[
particle| particle != particle1]){
var minDistance = particle1.radius + particle2.radius;
if( abs(particle1.x - particle2.x) < minDistance and i==0){//столкновение
i=1;
System.out.println("Particle collision!");
d(particle1, particle2);
}
}
}
for (particle in particles){//движение
particle.x = particle.dX * dt + particle.x;
particle.y = particle.dY * dt + particle.y;
for (particle1 in particles){ //торможение
for (particle2 in particles){
if (Math.sqrt(particle1.x*particle1.x+particle1.y*particle1.y)>150 or (
Math.sqrt(particle2.x*particle2.x+particle2.y*particle2.y)>150) )
{
particle1.dX=0;
particle1.dY=0;
particle2.dX=0;
particle2.dY=0;
}
}
}
}
}
function create():Node{
return Group{
content: [
for (particle in particles)
Circle{
radius: particle.radius
fill: bind particle.color
centerX: bind particle.x
centerY: bind particle.y
}
]
}
}
}
var particleSystem = ParticleSystem{
transform: Transform.translate(250, 200)
particles: [
Particle{
name: "Particle 1"
mass: m1
radius: 4
x: -149
y: 0
dX: 10
dY: 0
color: Color.GREEN
},
Particle{
name: "Particle 2"
mass: m2
radius: 4
x: 0
y: 0
dX: 0
dY: 0
color: Color.RED
}
]
};
var timeline = Timeline {
keyFrames: KeyFrame { time: 0.01s, action: function() { particleSystem.run()
} }
repeatCount: java.lang.Double.POSITIVE_INFINITY
}
timeline.start();
Frame{
title: "Particle Collision"
width: 500
height: 400
closeAction: function(){ System.exit(0);
}
stage: Stage{
content: particleSystem
}
visible: true
}
Пример того, как можно задавать начальные данные для частиц:
import javafx.ext.swing.*;
public class SetupParticleSystem extends CustomNode{
public attribute particles:Particle[];
public attribute run:Boolean;
attribute index:Integer on replace{
mass = "{particles[index].mass}";
radius = "{particles[index].radius}";
};
attribute mass:String on replace{
particles [index].mass = java.lang.Double.parseDouble(mass);
};
attribute radius:String on replace{
particles [index].radius = java.lang.Double.parseDouble(radius);
};
function create():Node{
return ComponentView {
component: BorderPanel{
left: List{
items: bind
for (particle in particles)
ListItem{
text: particle.name
}
selectedIndex: bind index with inverse
}
center: FlowPanel{ content: GridPanel{
columns: 2, rows: 2
content: [
Label{ text: "Mass"}, TextField{ columns: 7, text: bind mass with inverse},
Label{ text: "Radius"}, TextField{ columns: 7, text: bind radius with inverse},
]
} }
right: FlowPanel{
content: Button{
text: bind if(run) then "Stop" else "Run"
action: function(){ run = not run;}
}
}
}
}
}
}
Frame{
title: "Particle Collision"
width: 500
height: 400
closeAction: function(){
System.exit(0);
}
stage: Stage{
content: [
SetupParticleSystem{ particles: particleSystem.particles},
particleSystem
]
}
visible: true
}



