// Slab3D.java // This class implements a 3D slab cloud. import java.awt.*; import java.util.*; public class Slab3D extends Cloud { public int Dimension() { return(3); } public Slab3D(double od) { int i; data=new DataSet2D(20,10); data.SetSortOrder(DataSet2D.SORT_Y); for(i=0; i<20; i++) { data.AddElement(new Point2D(od,(double)i/19.0)); } } // 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(2)<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<20; i++) { try { ret+=data.GetElement(i).x; } catch(DataSet.DataException e) {} } return(ret/20.0); } private double OpticalDensity(RTVector r) { double ret; try { ret=data.Interpolate(r.Get(2)); } catch(DataSet2D.InterpolationException e) { return(0.0); } return(ret); } public boolean IsInCloud(RTVector r) { if((r.Get(2)>0.0) && (r.Get(2)<=1.0)) return(true); return(false); } public boolean IsBelowCloud(RTVector r) { if(r.Get(2)<=0.0) return(true); return(false); } public RTVector RandomStartLocation(RTVector dir) { RTVector ret=new RTVector(dir.Dimension()); ret.Set(0,0.5); ret.Set(1,0.0); ret.Set(2,1.0); return(ret); } public void DrawCloud(Panel p) { Graphics g=p.getGraphics(); int j; int edge1,edge2; float white; edge1=0; for(j=18; j>=0; j--) { edge2=p.size().height*(19-j)/19; try { white=(float)(1.0-Math.exp(-data.GetElement(j).x/20.0)); g.setColor(new Color(white,white,1.0f)); g.fillRect(0,edge1,p.size().width,edge2); edge1=edge2; } 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; i