/** applet No. 1153 * * meteor - astro object 3D (discrete element method) * - multi thread AO3D :: display - asynchronous * * Created by Ikeuchi Mitsuru on April 08 2007. * Copyright (c) 2007 Ikeuchi Mitsuru. All rights reserved. * * ver 0.0.1 2007.04.08 created * ver 0.0.2 2007.06.19 improved code * */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class meteorMtAO3D extends Applet implements MouseListener, MouseMotionListener, ItemListener, ActionListener, AdjustmentListener, Runnable { // ------------------------------------ preset field ----------- Thread th = null; // for run()-paint() thread AO3D d3d = null; DisplayD3D dsp = new DisplayD3D(); // 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 (d3d == null) { d3d = new AO3D(); d3d.start(); } if (th == null) { th = new Thread(this); th.start(); } } public void stop() { if (th != null) th = null; if (d3d != null) d3d = 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){ d3d.reset(); thCount = 0; } else if (ev.getSource() == bt_startStop){ if (d3d.getStartSW()==0) { d3d.setStartSW(1); } else { d3d.setStartSW(0); } } else if (ev.getSource() == bt_step){ if (d3d.getStartSW()==0) { d3d.setStepSW(); } } } public void adjustmentValueChanged(AdjustmentEvent ev){ if (ev.getSource() == sc_vx0) { d3d.setVx0( 1.0*(double)(sc_vx0.getValue())-100.0 ); } else if (ev.getSource() == sc_scale) { dsp.setViewScale( 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 (d3d != null) { dsp.plotGraph(gOff, d3d, dispMode, thCount); } } } // ================================= display D3D class =========== class DisplayD3D { Graphics gOff; AO3D d3d; private int Nmt; private double xMax = 100.0*1.0e5;; private double yMax = 100.0*1.0e5;; private double zMax = 100.0*1.0e5;; private double AU = d3d.AU; private double AA = d3d.AA; private double zDepth = xMax; private double dispWidth = 250.0; private double dispScale = (dispWidth/xMax); private double viewScale = 1.0; private double cx = 0.5*xMax; private double cy = 0.5*yMax; private double cz = 0.5*zMax; private double theta = -20.0*3.14/180.0; private double fai = 10.0*3.14/180.0; private int NN = 10000; private int srtz[][] = new int[2][NN]; private double px[] = new double[NN]; private double py[] = new double[NN]; private double pz[] = new double[NN]; private double wkx[] = new double[8]; private double wky[] = new double[8]; private double wkz[] = new double[8]; private double pwkx[] = new double[8]; private double pwky[] = new double[8]; private double pwkz[] = new double[8]; private int boxp[][] = { {0,1},{0,2},{0,4},{1,3},{1,5},{2,3},{2,6},{4,5},{4,6},{3,7},{5,7},{6,7} }; private int drawnCount = 0; // ------------------------------- class constructor ----------- DisplayD3D() { setWaku(); } // ----------------------------------- class methods ----------- public void plotGraph(Graphics gg, AO3D ad3d, int dispMode, int thCount) { int d3dCount, gbx, gby, gx; gOff = gg; d3d = ad3d; if (d3d==null) return; d3dCount = d3d.getCount(); if (d3dCount==drawnCount) return; drawnCount = d3dCount; Nmt = d3d.getNmt(); gOff.setColor(Color.black); gOff.fillRect(0,0,630,460); rotate(theta,fai); zSort(); gbx = 70; gby = 120; if (dispMode==0) { ballPlot(gbx,gby, 0); } else if (dispMode==1) { ballPlot(gbx,gby, 1); } else if (dispMode==2) { velocity3DPlot(gbx,gby, 20.0); } else if (dispMode==3) { ; } gbx = 630/6; gOff.setColor(Color.yellow); gOff.drawString("t="+(int)(d3d.getTime()+0.5)+" s",gbx*0+10,40); if (d3d.getStartSW()==1) { gOff.drawString("started",630/6*1+10,40); } else { gOff.drawString("stop",630/6*1+10,40); } gOff.drawString("vx0="+(int)(d3d.getVx0()*10.0+0.5)/10.0+"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/1000.0+0.5)+" x "+(int)(yMax/1000.0+0.5)+" x "+(int)(zMax/1000.0+0.5)+" km",400,60); gOff.drawString("thread AO3D = "+d3d.getCount()+" ",400,80); gOff.drawString("thread disp = "+thCount+" ",400,100); } // ------------------------------------ plot methods ----------- private void ballPlot(int gbx, int gby,int imode) { int i,j,gx,gy,gr; double sz,sc,den; drawWaku(gbx,gby,0); sc = dispScale*viewScale; sz = 1.0*viewScale/AA; for (i=0; i0.999) den = 0.999; if (den<0.3) den = 0.3; gOff.setColor(Color.getHSBColor(d3d.getColorOf(j),0.8f,(float)(den))); if (imode==0) { gOff.fillOval(gx-gr/2,gy-gr/2, gr, gr); } else if (imode==1) { gOff.drawOval(gx-gr/2,gy-gr/2, gr, gr); } } drawWaku(gbx,gby,1); } private void velocity3DPlot(int gbx, int gby, double mag) { int i,j,gx,gy,g2x,g2y,gr; double sc,sz,m,p2x,p2y,p2z,rotp2x,rotp2y,rotp2z,dt,den; double cosTh,sinTh,cosFi,sinFi; dt = d3d.getdt(); drawWaku(gbx,gby,0); cosTh = Math.cos(theta); sinTh = Math.sin(theta); cosFi = Math.cos(fai); sinFi = Math.sin(fai); sc = dispScale*viewScale; sz = 0.3*viewScale/AA; for (i=0; i0) { gOff.setColor(Color.cyan); } else { gOff.setColor(Color.red); } gOff.drawLine(gx,gy, g2x,g2y); den = 0.4*pz[j]/zDepth+0.3; if (den>0.999) den = 0.999; if (den<0.3) den = 0.3; gOff.setColor(Color.getHSBColor(d3d.getColorOf(j),0.8f,(float)(den))); gOff.fillOval(gx-gr/2,gy-gr/2, gr, gr); } drawWaku(gbx,gby,1); } private void drawWaku(int gbx, int gby, int imode) { int i,gx,gy,g2x,g2y,farPoint; double sc,tmp; sc = dispScale*viewScale; farPoint = findMin(); for (i=0; i<12; i++) { gx = (int)(sc*pwkx[boxp[i][0]])+gbx; gy = (int)(sc*pwky[boxp[i][0]])+gby; g2x = (int)(sc*pwkx[boxp[i][1]])+gbx; g2y = (int)(sc*pwky[boxp[i][1]])+gby; if (imode==0) { if (boxp[i][0]==farPoint || boxp[i][1]==farPoint) { gOff.setColor(Color.darkGray); gOff.drawLine(gx,gy, g2x, g2y); } } else if (imode==1) { if (boxp[i][0]!=farPoint && boxp[i][1]!=farPoint) { gOff.setColor(Color.gray); gOff.drawLine(gx,gy, g2x, g2y); } } } } private int findMin() { int i,im; double m; im = 0; m = pwkz[im]; for (i=0; i<8; i++) { if (pwkz[i]=srtz[1][p]) p = i; k = qSortPartition(i,j,srtz[1][p]); qSort(i,k-1); qSort(k,j); } } private int qSortPartition(int i,int j, int x) { int l,r,w; l = i; r = j; while (l<=r) { while (l<=j && srtz[1][l]=i && srtz[1][r]>=x) r--; if (l>r) break; w = srtz[0][l]; srtz[0][l] = srtz[0][r]; srtz[0][r] = w; w = srtz[1][l]; srtz[1][l] = srtz[1][r]; srtz[1][r] = w; l++; r--; } return ( l ); } // rotate private void rotate(double th,double fi) { int i; double cosTh,sinTh,cosFi,sinFi,x,y,z; cosTh = Math.cos(th); sinTh = Math.sin(th); cosFi = Math.cos(fi); sinFi = Math.sin(fi); for (i=0; i0) { 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,6, 3.0e6,0.0,5.0e6, vx0,0.0,0.0, 2); i = setNNCloud(i,6, 3.0e6,5.0e6,5.0e6, -vx0,0.0,0.0, 2); //i = setNNMeteor(i,5, 13.0e6,2.5e6,5.0e6, 0.0,0.0,0.0, 2.0e-4, 2); Nmt = i; } private int setNNCloud(int ii,int nn, double xPos, double yPos, double zPos, double vvx0, double vvy0, double vvz0, int mat) { int i,ix,iy,iz; 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]; vz[i] += a2*ffz[i]; xx[i] += vx[i]*dt; yy[i] += vy[i]*dt; zz[i] += vz[i]*dt; } } forceCalc(); for (i=0; i0) { a2 = dtv2/aObject[kind[i]][0]; vx[i] += a2*ffx[i]; vy[i] += a2*ffy[i]; vz[i] += a2*ffz[i]; } } } private void forceCalc() { int i,j,k, ki,kj; double xij,yij,zij; double r2,rij,f,fxij,fyij,fzij; for(i=0;i