xxxxxxxxxx
/* OpenProcessing Tweak of *@*http://www.openprocessing.org/sketch/83881*@* */
/* !do not delete the line above, required for linking your tweak if you re-upload */
// 3-body Convergence to orbit
// Conclusion: two or three bodies in motion converge to an orbital plane.
// Sometimes, it can be observed that three bodies begin in a chaotic motion, but
// over time, tend toward a stable circular orbit on a plane.
//import peasy.*; // import the camera class
//PeasyCam cam; // create a variable of the camera type
float ATT_FORCE = 8.0; //15
ArrayList p;
int TAIL_LENGTH = 3000; //133
float FRICTION = 0.006;
float FOLLOW_SPEED = 30.0;
int C_TRAIL_LENGTH = 133;
PVector center, scenter;
ArrayList centrail;
void setup() {
size(900, 600, P3D);
//cam = new PeasyCam(this, 50, 50, 50, 350);
center = new PVector(0, 0, 0);
scenter = new PVector(0, 0, 0);
centrail = new ArrayList();
p = new ArrayList();
// add particles: position(x,y,z) and velocity (vx,vy,vz)
// 5-body stable system: ATT_FORCE = 8.0, FRICTION = 0.006
p.add(new Particle(52.35978,54.302536,57.729527, 0.60067934,-0.08692667,-0.16620708)); // equatorial object pair
p.add(new Particle(40.986042,50.065533,51.611214, 0.12594731,0.30504084,0.5347937));
p.add(new Particle(53.198193,47.908867,42.23586, 0.15252762,-0.54623574,0.2382751)); // lateral three objects
p.add(new Particle(54.68025,56.452766,46.61339, -0.5164657,0.3274164,-0.1314804));
p.add(new Particle(48.521008,41.405273,51.679127, -0.34940693,0.0108878305,-0.48475575
));
/*
Somewhat related, there is a 5-body system at celestial coordinates:
09h 30m 10.78s, +53° 38' 59.5"
See: sci.news/astronomy/science-quintuple-star-system-02994.html
*/
/* p.add(new Particle(72.911385,-79.57099,66.10063, 0.6386424,0.29552653,-0.18966271));
p.add(new Particle(68.11238,-80.934265,63.334793, -0.103960745,-0.18389837,0.69461244));
p.add(new Particle(72.349434,-78.56897,60.098843, -0.53416353,-0.118222736,-0.47169796
));
p.add(new Particle(24.61437,9.058599,22.342901, -0.25544724,-0.39705524,0.4392776));
p.add(new Particle(30.685595,7.5981555,24.802086, -0.3978609,0.3099903,-0.41481313));
p.add(new Particle(25.550106,4.7050056,27.608974, 0.6514069,0.10372401,-0.044413056
));
p.add(new Particle(50.575146,45.02966,55.80123, 0.25347427,-0.20834376,-0.4256102));
p.add(new Particle(43.90608,43.815548,47.991257, -0.24536425,-0.07970174,0.47753793));
p.add(new Particle(49.652363,56.338093,54.501675, -0.51857895,0.13377638,0.050050486));
p.add(new Particle(45.032166,54.868813,45.559605, 0.5204944,0.1291443,-0.082118675));
*/
centerMass();
for (int i = 0 ; i < p.size();i++) { // place center of mass at 50,50,50
Particle tmp = (Particle)p.get(i);
tmp.pos.x += 50-center.x;
tmp.pos.y += 50-center.y;
tmp.pos.z += 50-center.z;
}
perspective(PI/3f, float(width)/float(height), 1f, 23500f*1.5f);
//frameRate(10);
}
void draw() {
background(255);
translate(450-50,300-50,440);
pushMatrix();
translate(50,50,50);
noFill(); stroke(0); strokeWeight(0.5);
box(100);
popMatrix(); strokeWeight(1);
scenter.x += (center.x-scenter.x) / FOLLOW_SPEED;
scenter.y += (center.y-scenter.y) / FOLLOW_SPEED;
scenter.z += (center.z-scenter.z) / FOLLOW_SPEED;
pushMatrix();
// translate(-scenter.x+width/2, -scenter.y+height/2, scenter.z);
noFill();
stroke(#ff0000);
for (int i = 1 ; i < centrail.size();i++) {
PVector tmp1 = (PVector)centrail.get(i-1);
PVector tmp2 = (PVector)centrail.get(i);
//strokeWeight(map(i, 0, centrail.size(), 1, 5));
stroke(#ff0000, map(i, 0, centrail.size(), 5, 90));
line(tmp1.x, tmp1.y, tmp1.z, tmp2.x, tmp2.y, tmp2.z);
}
// strokeWeight(1);
fill(#ff0000);
pushMatrix();
translate(center.x, center.y, center.z);
//box(0.5);
popMatrix();
noFill();
for (int i = 0 ; i < p.size();i++) {
Particle tmp = (Particle)p.get(i);
tmp.move();
}
centerMass();
for (int i = 0 ; i < p.size();i++) {
Particle tmp = (Particle)p.get(i);
tmp.drawTail();
}
for (int i = 0 ; i < p.size();i++) {
Particle tmp = (Particle)p.get(i);
switch(i) {
case 0: fill(0,0,255); break;
case 1: fill(0,255,0); break;
case 2: fill(255,128,0); break;
case 3: fill(0,255,255); break;
default: fill(0); break;
}
tmp.draw();
}
noFill();
centrail.add(new PVector(center.x, center.y, center.z));
if (centrail.size()>C_TRAIL_LENGTH)
centrail.remove(0);
popMatrix();
/*cam.beginHUD();
float[] rotations = cam.getRotations(); // x, y, and z rotations required to face camera in model space
double dist = cam.getDistance(); // current distance
float[] look = cam.getLookAt(); // float[] { x, y, z }, looked-at point
fill(127);
text("lookAt="+round(look[0])+", "+round(look[1])+", "+round(look[2])+", "+round((float)dist)+" rotation="+round(rotations[0]*180/PI)+", "+round(rotations[1]*180/PI)+", "+round(rotations[2]*180/PI), 10, height-10);
cam.endHUD();*/
}
void centerMass() {
// calculate center of mass
center.x = 0; center.y = 0; center.z = 0;
for (int i = 0 ; i < p.size();i++) {
Particle tmp = (Particle)p.get(i);
center.x += tmp.pos.x;
center.y += tmp.pos.y;
center.z += tmp.pos.z;
}
center.x = center.x/(p.size()+0.0);
center.y = center.y/(p.size()+0.0);
center.z = center.z/(p.size()+0.0);
}
void keyPressed() {
if (key == ' ') {
//cam.lookAt(scenter.x, scenter.y, scenter.z, 300);
}
if (key == 's')
for (int i = 0 ; i < p.size();i++) {
Particle tmp = (Particle)p.get(i);
println(tmp.pos.x+","+tmp.pos.y+","+tmp.pos.z+", "+tmp.vel.x+","+tmp.vel.y+","+tmp.vel.z);
}
if (key == 'p') {
p.add(new Particle());
}
if (key == 'r') {
if (p.size()>=1)
p.remove(p.size()-1);
}
}