/** applet No. 1152 * * meteor 3-body - astro object 2D (discrete element method) * - multi thread AO2D :: display - asynchronous * * Created by Ikeuchi Mitsuru on April 07 2007. * Copyright (c) 2007 Ikeuchi Mitsuru. All rights reserved. * * ver 0.0.1 2007.04.07 created * ver 0.0.2 2007.06.19 improved code * */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class meteor3BodyMtAO2D extends Applet implements MouseListener, MouseMotionListener, ItemListener, ActionListener, AdjustmentListener, Runnable { // ------------------------------------ preset field ----------- Thread th = null; // for run()-paint() thread AO2D d2d = null; DisplayD2D dsp = new DisplayD2D(); // for event Choice ch_mat,ch_view; Button bt_reset, bt_startStop, bt_step; Scrollbar sc_vx0, sc_scale; // for off-paint buffer Dimension dim; Image imgOff; Graphics gOff; int dgX, dgY, dgXb, dgYb; int sleepTime = 30; int dispMode = 0; int thCount = 0; // ------------------------------ applet main thread ----------- public void init() { resize(630,460); setBackground(Color.white); dim = getSize(); imgOff = createImage(dim.width,dim.height); gOff = imgOff.getGraphics(); ch_mat = new Choice(); ch_mat.add("fixed"); ch_mat.add("A"); ch_mat.add("B"); ch_mat.add("C"); ch_mat.addItemListener(this); ch_mat.select("B"); ch_view = new Choice(); ch_view.add("ball"); ch_view.add("openBall"); ch_view.add("velocity"); ch_view.addItemListener(this); ch_view.select("ball"); bt_reset = new Button("reset"); bt_reset.addActionListener(this); bt_startStop = new Button("start/stop"); bt_startStop.addActionListener(this); bt_step = new Button("step"); bt_step.addActionListener(this); sc_vx0 = new Scrollbar(Scrollbar.HORIZONTAL,135,10,0,210); sc_vx0.addAdjustmentListener(this); sc_scale = new Scrollbar(Scrollbar.HORIZONTAL,100,10,50,510); sc_scale.addAdjustmentListener(this); addMouseListener(this); addMouseMotionListener(this); setLayout(new BorderLayout()); Panel pnl = new Panel(); pnl.setLayout(new GridLayout(1,6,5,0)); /* pnl.add(new Label(" ")); */ pnl.add(bt_reset); pnl.add(bt_startStop); pnl.add(sc_vx0); pnl.add(new Label(" ")); pnl.add(sc_scale); pnl.add(ch_view); add(pnl,"North"); } public void start() { if (d2d == null) { d2d = new AO2D(); d2d.start(); } if (th == null) { th = new Thread(this); th.start(); } } public void stop() { if (th != null) th = null; if (d2d != null) d2d = null; } // ---------------------------------- event listener ----------- public void itemStateChanged(ItemEvent ev){ if (ev.getSource() == ch_view){ dispMode = ch_view.getSelectedIndex(); } } public void actionPerformed(ActionEvent ev){ if(ev.getSource() == bt_reset){ d2d.reset(); thCount = 0; } else if (ev.getSource() == bt_startStop){ if (d2d.getStartSW()==0) { d2d.setStartSW(1); } else { d2d.setStartSW(0); } } else if (ev.getSource() == bt_step){ if (d2d.getStartSW()==0) { d2d.setStepSW(); } } } public void adjustmentValueChanged(AdjustmentEvent ev){ if (ev.getSource() == sc_vx0) { d2d.setVx0( 1.0*(double)(sc_vx0.getValue())-100.0 ); } else if (ev.getSource() == sc_scale) { dsp.setScale( 0.01*(double)(sc_scale.getValue()) ); } } public void mousePressed(MouseEvent ev){ } public void mouseReleased(MouseEvent ev){ dgXb = 0; dgYb = 0; dgX = 0; dgY = 0; } public void mouseClicked(MouseEvent ev){ } public void mouseEntered(MouseEvent ev){ } public void mouseExited (MouseEvent ev){ } public void mouseMoved (MouseEvent ev){ } public void mouseDragged(MouseEvent ev){ dgXb = dgX; dgYb = dgY; dgX=ev.getX(); dgY=ev.getY(); if (dgXb==0 && dgYb==0) { dgXb = dgX; dgYb = dgY; } dsp.setViewDelta( (dgX-dgXb), (dgY-dgYb) ); } // ========================= run() - paint() loop ============== public void run() { while (th != null) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } thCount += 1; offPaint(); repaint(); } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.drawImage(imgOff,0,0,this); } private void offPaint() { if (d2d != null) { dsp.plotGraph(gOff, d2d, dispMode, thCount); } } } // ================================= display D2D class =========== class DisplayD2D { Graphics gOff; AO2D d2d; private double xMax = 100.0*1.0e5; private double yMax = 100.0*1.0e5; private int Nmt = 0; private double dispWidth = 300.0; private double dispScale = (dispWidth/xMax); private double viewScale = 1.0; private double xShift = 0.0; private double yShift = 0.0; private int drawnCount = 0; DisplayD2D() { } public void plotGraph(Graphics gg, AO2D ad2d, int dispMode, int thCount) { int d2dCount, gx, gy, gbx; double sc; gOff = gg; d2d = ad2d; if (d2d==null) return; d2dCount = d2d.getCount(); if (d2dCount==drawnCount) return; drawnCount = d2dCount; Nmt = d2d.getNmt(); sc = dispScale*viewScale; gx = 30+(int)(sc*xShift); gy = 80+(int)(sc*yShift); gOff.setColor(Color.black); gOff.fillRect(0,0,630,460); drawWaku(gx,gy,sc); if (dispMode==0) { ballPlot(gx,gy,sc,0); } else if (dispMode==1) { ballPlot(gx,gy,sc,1); } else if (dispMode==2) { ballPlot(gx,gy,sc,0); velocityPlot(gx,gy,sc,0.2); } else if (dispMode==3) { ; } gbx = 630/6; gOff.setColor(Color.yellow); gOff.drawString("t="+(int)(d2d.getTime()*10.0+0.5)/10.0+" s",gbx*0+10,40); if (d2d.getStartSW()==1) { gOff.drawString("started",630/6*1+10,40); } else { gOff.drawString("stop",630/6*1+10,40); } gOff.drawString("vx0="+(float)(d2d.getVx0())+"m/s",gbx*2+10,40); gOff.drawString("scale="+(int)(viewScale*100.0+0.5)+"%",gbx*4+10,40); gOff.drawString("view",gbx*5+10,40); gOff.setColor(Color.yellow); gOff.drawString("Box="+(int)(xMax/100.0+0.5)/10.0+" x "+(int)(yMax/100.0+0.5)/10.0+" km",430,60); } // ------------------------------------ plot methods ----------- private void ballPlot(int gx, int gy, double sc, int mode) { int i,ix,iy,ir; double tm; for (i=0; i0) { gOff.setColor(Color.blue); } else { gOff.setColor(Color.red); } gOff.drawLine(ix,iy, ix2,iy2); } } private void drawWaku(int gx, int gy, double sc) { int ix,iy,gball,idx,idy; gball = (int)(3.0*viewScale); gOff.setColor(Color.darkGray); ix = (int)(sc*xMax); iy = (int)(sc*yMax); idx = ix+2*gball; idy = iy+2*gball; gOff.drawRect(gx-gball,gy-gball,idx,idy); } // ------------------------------------- I/O methods ----------- public void setViewDelta(double xDisplacement, double yDisplacement) { xShift += (1.0/viewScale/dispScale)*xDisplacement; yShift += (1.0/viewScale/dispScale)*yDisplacement; } public void setScale(double sc) { viewScale = sc; }; } // ============================= astro object 2D class =========== class AO2D extends Thread { private double t = 0.0; private double dt = 20.0; private int Nmt = 1000; private double gg = 6.673e-11; // m^3kg^-1s-2 private int incRate = 10; private double vx0 = 35.0; private double AU = 1.0e18; // kg private double AA = 1.0e5; // m private double AD = 1.0e10; // dump private double aObject[][] = { // 0:mass(AU) 1:r0(AA) 2:dump 3:color { 1.0*AU, 0.8*AA, 2.0*AD, 0.85 }, // fixed ball { 1.0*AU, 0.8*AA, 1.0*AD, 0.01 }, // 1 A { 5.0*AU, 0.8*AA, 2.0*AD, 0.10 }, // 2 B { 10.0*AU, 0.8*AA, 1.0*AD, 0.20 } // 3 C }; private String materialStr[] = { "fixed" ,"A" ,"B","C" }; private int NmatKind = 4; private int NN = Nmt + 1; private int kind[] = new int[NN]; private double xx[] = new double[NN]; private double yy[] = new double[NN]; private double vx[] = new double[NN]; private double vy[] = new double[NN]; private double ffx[] = new double[NN]; private double ffy[] = new double[NN]; private int resetSW = 0; private int startSW = 1; private int stepSW = 0; private int sleepTime = 1; private int stopSleepTime = 100; private int count = 0; // ------------------------------- class constructor ----------- AO2D() { setInitialCondition(); } // -------------------------------------- thread run ----------- public void run() { while (true) { count += 1; timeEvolution(); if (sleepTime>0) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } } // --------------------------- set initial condition ----------- private void setInitialCondition() { int i; t = 0.0; count = 0; i = 0; i = setNNCloud(i,10, 3.0e6, 0.0, vx0, 0.0, 2); i = setNNCloud(i,10, 3.0e6, 5.0e6, -vx0, 0.0, 2); i = setNNMeteor(i,5, 13.0e6, 2.5e6, 0.0, 0.0, 2.0e-4, 2); Nmt = i; } private int setNNCloud(int ii,int nn, double xPos, double yPos, double vvx0, double vvy0, int mat) { int i,ix,iy; double a; i = ii; a = 3.0e5; for (ix=0; ix0) { a2 = dtv2/aObject[kind[i]][0]; vx[i] += a2*ffx[i]; vy[i] += a2*ffy[i]; xx[i] += vx[i]*dt; yy[i] += vy[i]*dt; } } forceCalc(); for (i=0; i0) { a2 = dtv2/aObject[kind[i]][0]; vx[i] += a2*ffx[i]; vy[i] += a2*ffy[i]; } } } private void forceCalc() { int i,j,k, ki,kj; double xij,yij; double r2,rij,f,fxij,fyij; for(i=0;i