/* Diffract.java * Computes the fresnel diffration pattern of various obstacles. * by John Talbot, May 5,1997. */ class Table // Optical table of components { float a,b; Component c[3]; void Table() { c[0]=new Beam(); // source component c[1]=new Wire(); // obstacle component c[2]=new Video(); // screen component float wavelength=(Source) c[0].wavelength; float source =c[0].z; float obstacle=c[1].z; float screen =c[2].z; float a1=obstacle-source; //Source to Obstacle distance float a2=screen-obstacle; //Obstacle to Screen distance float a3=screen-source; //Source to Screen distance b=a3/a1; // ratio of big triangle to little triangle a=Math.sqrt(2/(wavelength*a2*b)); // Scaling down and SQR(2/(A3*L)) } public static complex fresnel3(float origin, float x) { // a, b and parameters contain screen, obstacle and source dependence return(complex.fresnel(a*(b*origin-x))); } public shadowVector(float x1, float y1, float x2, float y2) { // project shadow of obstacle onto screen c[2].Vector(b*x1, b*y1, b*x2, b*y2); } public void add(component c) { } public void remove(component c) { } } class abstract Component { float x=0, y=0, z=0; // location of the component (default = origin) String type; // either 'Source' , 'Obstacle' or 'Screen' Component(); { type=""; // required zero param constructor } Component(String type, float z) { this.z=z; // default on the optical axis this.type=type; } setPosition(float x, float y, float z) { this.x=x; // Can move the component this.y=y; this.z=z; } float getx() { return x; } float gety() { return y; } float getz() { return z; } String toString() { return type + " at ( " + x + ", " + y + ", " + z + ") "; } } class abstract Source extends Component { float wavelength=550e-9; // color (default = 550 nm) String name=""; // either 'Spherical', 'Beam' or 'Plane' Source() { super("Source", 0); } Source(String name, float wavelength, float z) { super("Source", z); this.wavelength=wavelength; this.name=name; } } class abstract Obstacle extends Component { String name=""; // either 'Edge', 'Slit', 'Wire', 'Two Slits' or 'Rectangle' Obstacle(String name, float z) { super("Obstacle", z); this.name=name; } // Set integration limits and compute intesity of diffraction patern abstract float amplitude(float x); // obstacle dependent implementation // N.B.: should modify amplitude() in near future so it can return a // complex value for plotting the wavefunction phase abstract void shadow(Color EdgeColor); // shadow cast by obstacle on screen String toString() { return name + super.toString(); } } class abstract Screen extends Component { float xMin=-20e-3; // All Screens have these members in common float xMax= 20e-3; String name=""; // either 'Detector', 'Video' or 'VRML' Screen(String name, float z, float xMin, float xMax) { super("Screen", z); this.xMin=xMin; this.xMax=xMax; this.name=name; } abstract Vector(float x1, float y1, float x2, float y2); } // Linear detector scans across diffraction pattern and // only produces a line graph class Detector extends Screen { int maxX=640; int maxY=480; float headRoom=2/100; // 2 percent beyond extremums int xBorder=5; int yBorder=18; int screenX=maxX-2*xBorder; int screenY=maxY-2*yBorder; Detector() { super(); } Dectector(float z, float xMin, float xMax) { super("Detector", z, xMin, xMax) } } // 2D Video detector scans a rectangular portion of the // diffraction pattern and plots a color-coded intensity pixels class Video extends Screen { float yMin=-20e-3; // extra dimension needed for 2D video detector float yMax= 20e-3; float a,b; Graphics g; // Graphic context for output int maxX=320; int maxY=200; int maxPt=maxX; // Increase this for super-sampling float aspect=1.3; float headRoom=0; // 0 percent beyond extremums int xBorder=0; int yBorder=0; int screenX=maxX-2*xBorder; int screenY=maxY-2*yBorder; Color edgeColor=65; Color titleColor=64; Color borderColor=66; Color overlayColor=64; Color plotColor=63; // GreyScales(); Video() { super("Video"); g=getGraphics(); } Video(float z, float xMin, float xMax, float yMin, float yMax) { super("Video", z, xMin, xMax); this.yMin=yMin; this.yMax=yMax; g=getGraphics(); // Need a Graphic context for plot } void Vector (float x1, float y1, float x2, float y2) { Integer xx1,yy1,xx2,yy2; // in case point is outside drawing area should handle // clipping and intersection with boundary here videoXY(x1,x1,xx1,yy1); videoXY(x2,x2,xx2,yy2); g.drawLine(java.lang.Integer.intValue(xx1), java.lang.Integer.intValue(yy1), java.lang.Integer.intValue(xx2), java.lang.Integer.intValue(yy2)); } void videoXY (float x, float y, Integer xx, Integer yy) { /* Map real world coordinates to screen coordinates */ if(x>xMax) /* clipping */ x=xMax; else if(xyMax) y=yMax; else if(y Rectangle THEN PRINT " 1. Screen graph of intensity versus position" PRINT " 2. Simulated laser spot pattern (in 2 dimensions)" PRINT " 3. Animation sweeping one parameter in time" PRINT " 4. Laser printer (LaserJetIIIp HPGL/2)" PRINT " 5. TellAGraf script" PRINT " What type of plot ?"; GetKey Plot, 5# PRINT if(Plot==Laser || Plot==TellAGraf) { Plotter++; Plotter$ = STR$(Plotter): FileName$ = CurrentDir$ + "Plot" + RIGHT$(Plotter$, LEN(Plotter$) - 1) System.out.println(" Will be saved to disk as % s", FileName); System.out.println(); } if(Plot==Laser || Plot==Video) { PRINT " 1. Plot overlay of undisturbed laser intensity" PRINT " 2. No Overlay" PRINT " Plot Characteristics ?"; GetKey OverlayFlag, 2# PRINT } else Plot==Simulation; } PRINT USING " #.####^^^^ mm What laser wavelength"; Wavelength; : GetNumber Wavelength PRINT USING " ####.# mm Source to obstacle distance"; A1; : GetNumber A1 PRINT USING " ####.# mm Obstacle to screen distance"; A2; : GetNumber A2 A=Math.sqrt(2*A1/(Wavelength*A2*(A1+A2))); // Scaling down and sqrt(2/(Wavelength*L)) B=(A1+A2)/A1; // Scaling up PRINT USING " ####.# mm Detector starts scanning at"; DomainMin; : GetNumber DomainMin PRINT USING " ####.# mm Detector stops scanning at"; DomainMax; : GetNumber DomainMax xRange=domainMax-domainMin; if(xRange<=0) { System.out.println("Illegal Range "); exit(0); } switch(Plot) { case : Video case : Animation MaxPt=ScreenX; break; case : Laser MaxPt=ScreenXL; //DO NOT not change this! break; case : TellAGraf MaxPt=ScreenXL; //can be changed break; } }; /*-------------------------------------------------------------*/ public void Constants() { None=1; Wire=2; Edge=3; Slit=4; TwoSlit=5 Rectangle=6; Quit=7; Obstacle=Wire; // default type of obstacle Video=1; Simulation=2; Animation=3; Laser=4; TellAGraf = 5 Plot=Video; // default type of plot Uniform=1; Gaussian=2; Bessel=3; Beam=Gaussian // default type beam PI=3.141592653589; // There must be a bug here! (improper scaling somewhere!) MAXX=640; MAXY=480; // Default Screen resolution MAXXL=3300; MAXYL=2400; // Laser printer resolution (HP LaserJetIIIp 300DPI) XBorderL=MAXXL*8/100; // should leave room for axis labels YBorderL=MAXYL*8/100; // and for axis coordinates ScreenXL=MAXXL-2*XBorderL; ScreenYL=MAXYL-2*YBorderL; // Make shure that MaxPt=ScreenXL otherwise PR (HPGL/2) command won't work String XAxis = "POSITION (mm)"; String YAxis = "INTENSITY (arbitrary units)"; PlotPen=0.09; // mm or 2 dots width TextPen=0.17; // mm or 2 dots width TitlePen=0.34; // mm or 4 dots width BorderPen=0.34; // mm or 4 dots width ThickPen=.51; // mm or 6 dots width FatPen=1.19; // mm or 14 dots width mm=25.4/300; // Multiply Dots by mm to obtain millimeters (300 DPI) PenSize=TextPen; String CurrentDir="C:"; // Output directory Plotter=0; // PCL5 and HPGL/2 plot file number for LaserJetIIIp. } void scale() { max=-1E+20; min= 1E+20; for(pt=0; ptmax) max=y; if(y None THEN GOSUB OverLay COLOR TitleColor: LOCATE 1, 5: PRINT Title$ LOCATE 30, 1: PRINT USING "###.##"; DomainMin; LOCATE 30, 74: PRINT USING "###.##"; DomainMax; LOCATE 30, 35: PRINT XAxis$; : LOCATE 1, 1: X = DomainMin dX = XRange / (MaxPt - 1) Y = Y!(0) VideoXY X, Y, XS, YS PSET (XS, YS), PlotColor 'Start first point on plot Yp = INT(YBorderL + YScaleL * (Y!(0) - Min)) IF Plot = Laser THEN Y = Y!(0): LaserXY X, Y, X$, Y$ PRINT #Plotter, USING "PU; PW ##.##;"; PlotPen; PRINT #Plotter, "PA"; X$; Y$; "; PD;" END IF Y$ = "PR" FOR j = 1 TO MaxPt - 1 X = X + dX IF Plot = Laser THEN Y = INT(YBorderL + YScaleL * (Y!(j) - Min)) Y$ = Y$ + " 1" + STR$(Y - Yp) Yp = Y IF LEN(Y$) > 75 THEN PRINT #Plotter, Y$; ";": Y$ = "PR" END IF Y = Y!(j): VideoXY X, Y, XS, YS LINE -(XS, YS), PlotColor NEXT j IF LEN(Y$) > 2 AND Plot = Laser THEN PRINT #Plotter, Y$; ";" IF Plot = Laser THEN 'Restore defaults, Enter PCL Mode, Force page out and reset the printer PRINT #Plotter, "SP1; LT; TR1;"; CHR$(27); "%1A"; CHR$(27); "E" CLOSE Plotter END IF RETURN '---------------------------------------------------------------------- 'Plot on top of diffraction pattern the undisturbed laser beam OverLay: X = DomainMin dX = XRange / (MaxPt - 1) YJ = 1: GOSUB Convolve 'Output is YJ VideoXY X, YJ, XS, YS PSET (XS, YS), OverlayColor 'Start first point on plot of undisturbed beam Yp = INT(YBorderL + YScaleL * (YJ - Min)) IF Plot = Laser THEN LaserXY X, YJ, X$, Y$ PRINT #Plotter, USING "PU; LT2,2,0; PW ##.##;"; PlotPen; PRINT #Plotter, "PA"; X$; Y$; "; PD;" END IF Y$ = "PR" FOR j = 1 TO MaxPt - 1 X = X + dX YJ = 1: GOSUB Convolve IF Plot = Laser THEN Y = INT(YBorderL + YScaleL * (YJ - Min)) Y$ = Y$ + " 1" + STR$(Y - Yp) Yp = Y IF LEN(Y$) > 75 THEN PRINT #Plotter, Y$; ";": Y$ = "PR" END IF VideoXY X, YJ, XS, YS LINE -(XS, YS), OverlayColor NEXT j IF LEN(Y$) > 2 AND Plot = Laser THEN PRINT #Plotter, Y$; ";" IF Plot = Laser THEN PRINT #Plotter, "LT;" RETURN '------------------------------------------------------ LaserCoordinates: 'Print axis labels and title PRINT #Plotter, USING "PU; PW ##.##;"; TextPen; PRINT #Plotter, "DT#; SB; SD; SR 1.1,2.0; LO 14; DR 0,1; PA"; PRINT #Plotter, STR$(INT(XBorderL / 2)); STR$(INT(MAXYL / 2)); ";PD;"; PRINT #Plotter, "LB"; YAxis$; "#; PU;" PRINT #Plotter, "LO 16; DR 1,0; PA"; PRINT #Plotter, STR$(INT(MAXXL / 2)); STR$(INT(YBorderL / 2)); "; PD;"; PRINT #Plotter, "LB"; XAxis$; "#; PU;" PRINT #Plotter, USING "PW ##.##;"; TitlePen; PRINT #Plotter, "LO 14; DR 1,0; PA"; PRINT #Plotter, STR$(INT(MAXXL / 2)); STR$(INT(MAXYL - YBorderL)); "; PD;"; PRINT #Plotter, "LB"; Title$; "#; PU;" 'Draw Box around graph LaserVector DomainMin, Min, DomainMax, Min, BorderPen LaserVector DomainMax, Min, DomainMax, Max, BorderPen LaserVector DomainMax, Max, DomainMin, Max, BorderPen LaserVector DomainMin, Max, DomainMin, Min, BorderPen 'Print axis ticks and values 'XAxis XTicSize = 10: IF XRange > 100 THEN XTicSize = XTicSize * 2 k = INT(DomainMin / XTicSize) + 1 PRINT #Plotter, "LO16; DR 1,0; " WHILE k * XTicSize < DomainMax X = k * XTicSize X$ = STR$(X): IF X >= 0 THEN X$ = RIGHT$(X$, LEN(X$) - 1) LaserVector X, Min, X, Min + YRange * .015#, BorderPen LaserXY X, Min, X1$, Y1$ PRINT #Plotter, USING "PW ##.##; "; TextPen; PRINT #Plotter, "PA"; X1$; Y1$; "; LB"; X$; "#; " k = k + 1 WEND YTicSize = 2 k = INT(Min / YTicSize) + 1 PRINT #Plotter, "LO18; " WHILE k * YTicSize < Max Y = k * YTicSize Y$ = STR$(Y): IF Y >= 0 THEN Y$ = RIGHT$(Y$, LEN(Y$) - 1) LaserVector DomainMin, Y, DomainMin + XRange * .015#, Y, BorderPen LaserXY DomainMin, Y, X1$, Y1$ PRINT #Plotter, USING "PW ##.##; "; TextPen; PRINT #Plotter, "PA"; X1$; Y1$; "; LB"; Y$; "#; " k = k + 1 WEND RETURN '---------------------------------------------------------------------- LaserShadow: Y = Min + YRange * .03 'LaserVector automatically performs hardclip if out of bounds IF Obstacle = Wire OR Obstacle = Slit THEN LaserVector B * XA, Y, B * XB, Y, FatPen ELSEIF Obstacle = Edge THEN LaserVector DomainMin, Y, B * XA, Y, FatPen ELSEIF Obstacle = TwoSlit THEN LaserVector B * XA, Y, B * XZ, Y, FatPen LaserVector B * XX, Y, B * XB, Y, FatPen END IF RETURN Coordinates: 'Draw Box around graph VideoXY DomainMin, Min, X1, Y1 VideoXY DomainMax, Max, X2, Y2 LINE (X1, Y1)-(X2, Y2), BorderColor, B RETURN '------------------------------------------------------ InitPrinter: OPEN FileName$ FOR OUTPUT AS Plotter '----LaserJet IIIp Plotter commands--- ' Reset Printer ' PageSize=Letter, Orientation=Portrait, TopMargin=0 ' PCL CursorX=0 dots, PCL CursorY=0 dots ' Set picture frame to 8 X 11 inch (decipoints), Anchor point at PCL cursor ' Enter HPGL/2 ' Initialize HPGL/2 environment (Origin at bottom left) ' (5760 decipoints = 8 inch, 7920 decipoints = 11 inch ) ' (2400 pixels = 8 inch, 3300 pixels = 11 inch ) ' ( 720 decipoints = 1 inch, 2.4 decipoints = 1 pixel) PRINT #Plotter, CHR$(27); "E"; PRINT #Plotter, CHR$(27); "&l2a1o0E"; PRINT #Plotter, CHR$(27); "*p0x0Y"; PRINT #Plotter, CHR$(27); "*c7920x5760y0T"; PRINT #Plotter, CHR$(27); "%1B" PRINT #Plotter, "IN;" ' Select Pen 1 ' Input Relative control points at bottom left and top right(normal), ' Set Custom user coordinates to 1/300 inch units ' ( 2400 dot units = 8 inch , 3300 dot units = 11 inch ) ' Line Atributes : line ends = round, line joins = round ' default Line Type PRINT #Plotter, "SP1; SC 0,3300,0,2400; LA 1,4,2,4; LT;" RETURN TellAGrafFile: OPEN FileName$ FOR OUTPUT AS Plotter q$ = CHR$(39) PRINT #Plotter, "GENERATE A PLOT." PRINT #Plotter, "X AXIS LABEL TEXT IS " + q$ + XAxis$ + q$ + "." PRINT #Plotter, "Y AXIS LABEL TEXT IS " + q$ + YAxis$ + q$ + "." PRINT #Plotter, "TITLE TEXT IS " + q$ + Title$ + q$ + "." PRINT #Plotter, "INPUT DATA." X = DomainMin dX = XRange / (MaxPt - 1) FOR Pt = 0 TO MaxPt - 1 PRINT #Plotter, USING "####.#### ##.####"; X; Y!(Pt) X = X + dX NEXT Pt PRINT #Plotter, "END OF DATA." PRINT #Plotter, "GO." CLOSE Plotter RETURN '------------------------------------------------------------ '------------------------------------------------------------ 'Color Graphics Intensive Section of program '------------------------------------------------------------ GreyScales: 'Approximates laser intensity using 64 levels of quantization, ' and roughly simulates laser color according to Wavelength. SCREEN 13 IF Wavelength * 1000000# > 620 THEN 'RED Red = 1: Green = 0: Blue = 0 ELSEIF Wavelength * 1000000# > 570 THEN 'YELLOW Red = 1: Green = 256&: Blue = 0 ELSEIF Wavelength * 1000000# > 520 THEN 'GREEN Red = 0: Green = 256&: Blue = 0 ELSEIF Wavelength * 1000000# > 480 THEN 'CYAN Red = 0: Green = 256&: Blue = 256& * 256& ELSE 'BLUE Red = 0: Green = 0: Blue = 256& * 256& END IF 'This method minimizes color fringing by linearly increasing 'the intensity by integer steps for each color component separately) FOR i = 0 TO 63 RGBColor& = Red * i + Green * i + Blue * i PALETTE i, RGBColor& LINE (i * ScreenX / 64, ScreenY / 3)-STEP(ScreenX / 64 - 1, ScreenY / 3), i, BF NEXT i RGBColor& = 63: PALETTE 64, RGBColor& RGBColor& = 256 * 63: PALETTE 65, RGBColor& RGBColor& = 256& * 256& * 63&: PALETTE 66, RGBColor& RGBColor& = 63& + 256& * 63&: PALETTE 67, RGBColor& LINE (0, ScreenY / 3)-(ScreenX - 1, 2 * ScreenY / 3), 63, B COLOR 63: LOCATE 6, 1: PRINT "Plotting in Progress ...." COLOR 66: LOCATE 20, 5: PRINT "Adjust your monitor for linear scale" COLOR 65: LOCATE 22, 1: PRINT Title$; : LOCATE 1, 1 RETURN '------------------------------------------------------------ 'Plot the diffraction in 2 dimensions of a rectangular hole void Rectangular() { Scale(); MaxSpot=Max-YRange*HeadRoom // reduce this for fainter detail Min=-Aspect*ScreenY/(2*XScale); Max=-Min; YRange=Max-Min; YScale=ScreenY/YRange; for(int j=0; j255) Z=255; // set to maximum saturation PSET (i, j), Z; } } } '------------------------------------------------------ void LaserSpot() { int X; Color Z; Graphics g = getGraphics(); Scale(); MaxSpot=Max-YRange*HeadRoom; // reduce this for fainter detail if(Beam==Gaussian) { for(int j=0;j255) Z=255; // set to maximum saturation g.setColor(Z); g.drawRect(i,j,1,1); } } } else if(Beam==Uniform) for(int i=0; i255) Z=255; // set to maximum saturation g.setColor(Z); g.drawLine(i,0,i,MAXY-1); } else if(Beam==Bessel) { for(int j=0; j255) Z=255; // set to maximum saturation g.setColor(Z); g.drawRect(i,j,1,1); } } } WHILE INKEY$ = "": WEND X = DomainMin: dX = XRange / (MaxPt - 1) Temp = Y!(0) VideoXY X, Temp, X1, Y1 PSET (X1, Y1), PlotColor FOR i = 0 TO ScreenX - 1 Temp = Y!(i) VideoXY X, Temp, X1, Y1 LINE -(X1, Y1), PlotColor X = X + dX NEXT i GOSUB Shadow RETURN PlotEdge: RETURN SUB BesselJ1 (Rho, j1) STATIC n% = 1.1 * ABS(Rho) + 15 IF n% > 499 THEN n% = 499 j(n%) = 0 j(n% - 1) = 1E-12 Factor = 2 / Rho FOR k% = n% - 1 TO 1 STEP -1 j(k% - 1) = (Factor * k%) * j(k%) - j(k% + 1) NEXT k% Sum = 0 FOR k% = 2 TO n% STEP 2 Sum = Sum + j(k%) NEXT k% Sum = j(0) + 2 * Sum j1 = j(1) / Sum END SUB SUB GetKey (Choice, Maximum) STATIC A$ = "" WHILE A$ = "": A$ = INKEY$: WEND A = ASC(A$) - ASC("0") IF A > 0 AND A <= Maximum THEN Choice = A END IF PRINT Choice END SUB SUB GetNumber (Number) STATIC 'if user entered RETURN without typing in a numeric value 'then Number retains its original default value. INPUT Entry IF Entry <> 0 THEN Number = Entry END SUB public float Intensity(float X, float Y) { return (X*X+Y*Y)/2; }; /* Should output this to a VRML file format in future */ LaserVector(float X1, float Y1, float X2, float Y2, float ThePenWidth) { String X1s,Y1s,X2s,Y2s; LaserXY(X1,Y1,X1s,Y1s); LaserXY(X2,Y2,X2s,Y2s); System.out.println("PU; PW %3.2f ; PA %s %s ; PD %s %s ; PU;", ThePenWidth,X1s,Y1s,X2s,Y2s); } void LaserXY (float X, float Y, String X, String Y) { /* Map real world coordinates to screen coordinates */ if(X>DomainMax) /* clipping */ X=DomainMax; else if(XMax) Y=Max; else if(Y