// Sphere2D.java // Implements a circular 2D cloud. import java.awt.*; import java.util.*; public class Sphere2D extends Cloud { public Sphere2D(double od) { int i; data=new DataSet2D(10,10); data.SetSortOrder(DataSet2D.SORT_Y); for(i=0; i<10; i++) { data.AddElement(new Point2D(od,(double)i/9.0)); } } public int Dimension() { return(2); } // The only requirement to use this ScatterAt function is that when the // last component of the vector is zero you are out of the cloud. public RTVector ScatterAt(RTVector r,RTVector dir) { RTVector ret=new RTVector(r),next; double tau,p; double density1,density2; dir.Normalize(); // First calculate an optical depth to use. p=Math.random(); if(p<1e-3) { if(dir.Get(1)<0.0) { ret.Set(ret.Dimension()-1,0.0); } else { ret.Set(ret.Dimension()-1,1.01); } return(ret); } tau=-Math.log(p); // Now figure out where that is in the cloud. while(tau>0.0) { density1=this.OpticalDensity(ret); next=ret.Add(dir.Scale(0.01)); density2=this.OpticalDensity(next); if(tau<(density1+density2)*0.01) { ret=ret.Add(dir.Scale(0.01*tau/((density1+density2)*0.01))); return(ret); } else { tau-=(density1+density2)*0.01; ret=next; } if(!IsInCloud(ret)) return(ret); } return(ret); } public double OpticalDepth() { int i; double ret=0; for(i=0; i<10; i++) { try { ret+=data.GetElement(i).x; } catch(DataSet.DataException e) {} } return(ret/10.0); } private double OpticalDensity(RTVector r) { double dist=DistFromCenter(r); double ret; try { ret=data.Interpolate(dist); } catch(DataSet2D.InterpolationException e) { return(0.0); } return(ret); } public boolean IsInCloud(RTVector r) { return(DistFromCenter(r)<=0.5); } public boolean IsBelowCloud(RTVector r) { return(r.Get(1)<0.5); } public RTVector RandomStartLocation(RTVector dir) { RTVector ret=new RTVector(2); ret.Set(0,0.5); ret.Set(1,0.5); ret=ret.Add(dir.Scale(-0.5)); return(ret); } public void DrawCloud(Panel p) { Graphics g=p.getGraphics(); int j,rad1,rad2; float white; g.setColor(Color.blue); g.fillRect(0,0,p.size().width,p.size().height); for(j=9; j>=0; j--) { try { white=(float)(1.0-Math.exp(-data.GetElement(j).x/20.0)); g.setColor(new Color(white,white,1.0f)); rad1=(j+1)*p.size().width/20; rad2=(j+1)*p.size().height/20; g.fillOval(p.size().width/2-rad1,p.size().height/2-rad2,rad1*2,rad2*2); } catch(DataSet.DataException e) {} } } public void DrawPath(Panel p,Vector v) { int i,x1,y1,x2,y2; RTVector rtv; Graphics g=p.getGraphics(); g.setColor(Color.yellow); for(i=1; i0) return(null); return(data); } private double DistFromCenter(RTVector r) { return(Math.sqrt((r.Get(0)-0.5)*(r.Get(0)-0.5)+(r.Get(1)-0.5)*(r.Get(1)-0.5))); } private DataSet2D data; }