From 6b08e5dc832db5913a21558dbbf9e4dbdb5c850b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 18 Feb 2010 15:35:53 -0500 Subject: [PATCH] Draw Laser and Photodiode in AFM schematic. --- tex/src/figures/schematic/Makefile | 8 +- tex/src/figures/schematic/afm.asy | 33 ++++++ tex/src/figures/schematic/base_afm.asy | 131 +++++++++++++++++++----- tex/src/figures/schematic/unfolding.asy | 2 +- 4 files changed, 142 insertions(+), 32 deletions(-) create mode 100644 tex/src/figures/schematic/afm.asy diff --git a/tex/src/figures/schematic/Makefile b/tex/src/figures/schematic/Makefile index 2f440a6..7cf657c 100644 --- a/tex/src/figures/schematic/Makefile +++ b/tex/src/figures/schematic/Makefile @@ -1,7 +1,7 @@ -all : unfolding.pdf +all : unfolding.pdf afm.pdf clean : - rm -f unfolding.pdf + rm -f unfolding.pdf afm.pdf -unfolding.pdf : unfolding.asy base_afm.asy - asy -f pdf unfolding.asy +%.pdf : %.asy base_afm.asy + asy -f pdf $< diff --git a/tex/src/figures/schematic/afm.asy b/tex/src/figures/schematic/afm.asy new file mode 100644 index 0000000..432bdbb --- /dev/null +++ b/tex/src/figures/schematic/afm.asy @@ -0,0 +1,33 @@ +// AFM operating principle graphic + +//size(x=9cm,keepAspect=true); + +import base_afm; // for Cantilever, Substrate, ... + +defaultpen(fontsize(size=10pt, lineskip=10pt)); + +Cantilever c = Cantilever(); +// position base so tip touches substrate when bent +c.set_tip_for_dx(8pt); +c.align_tip((0,0)); +// unbend the tip and draw it in grey +c.set_tip_for_dx(0); +pair unbent_tip = c.tip; +filldraw(c.tip_guide(), fillpen=grey, grey); +draw(c.arm_guide(), grey); +// rebend the tip and draw it in black +c.set_tip_for_dx(8pt); +filldraw(c.tip_guide(), fillpen=black); +draw(c.arm_guide(), black); +label("Cantilever", c.base-(0,14pt), SW); + +Substrate s = Substrate(); +s.draw(); + +Photodiode p = Photodiode(center=(-40pt, 40pt)); +p.draw(); +label("Photodiode", p.center+(0,p.radius), N); + +Laser s = Laser(start=(-5pt,40pt), dir=S, cantilever=c, photodiode=p); +s.draw(); +label("Laser", s.start, N); diff --git a/tex/src/figures/schematic/base_afm.asy b/tex/src/figures/schematic/base_afm.asy index 1859b86..e73f127 100644 --- a/tex/src/figures/schematic/base_afm.asy +++ b/tex/src/figures/schematic/base_afm.asy @@ -4,20 +4,34 @@ struct Cantilever { // draw an AFM cantilever with the tip at TIP (x,y) position on page // the cantilever arm is roughly parallel to DIR_TO_BASE (x,y) vector // POINT_SCALE x gives the height of the tip. - pair tip; - pair tip_top; - pair base; - real arm_length; - real tip_height; - real rest_angle; // in degrees - real dx; - real theta; // in radians + pair tip; // point of the tip + pair tip_top; // center of the back side of the tip + pair tip_distal; // distal back corner of the tip + pair tip_proximal; // proximal back corner of the tip + + pair uty; // unit vector pointing distally at the tip + pair utx; // unit vector pointing tip-side at the tip + + pair base; // location of the cantilever base (chip attachment point) + + pair uy; // unit vector pointing distally at the base + pair ux; // unit vector pointing tip-side at the base + + real arm_length; // cantilever path length + real tip_height; // distance from tip_top to tip + real rest_angle; // in degrees. uy = dir(rest_angle) + real dx; // (tip_top offset from unbent) (ux) + real theta; // in radians real r_curve; + void align_tip(pair tip) { + // shift the whole cantilever setup so the tip rests on TIP. pair offset = tip - this.tip; this.tip += offset; this.tip_top += offset; + this.tip_distal += offset; + this.tip_proximal += offset; this.base += offset; } @@ -65,35 +79,30 @@ struct Cantilever { this.r_curve = this.arm_length / this.theta; Lp = this.r_curve * sin(this.theta); } - pair uy = dir(this.rest_angle); - pair ux = dir(this.rest_angle+90); - pair utx = dir(this.rest_angle+90+degrees(this.theta)); - this.tip = this.base + Lp*uy + (dx+this.tip_height)*utx; - this.tip_top = this.tip - this.tip_height*utx; + this.uy = dir(this.rest_angle); + this.ux = dir(this.rest_angle+90); + this.uty = dir(this.rest_angle+degrees(this.theta)); + this.utx = dir(this.rest_angle+90+degrees(this.theta)); + this.tip = this.base + Lp*this.uy + (dx+this.tip_height)*this.utx; + this.tip_top = this.tip - this.tip_height*this.utx; + this.tip_distal = this.tip_top + this.tip_height/3.0*this.uty; + this.tip_proximal = this.tip_top - this.tip_height/3.0*this.uty; } guide tip_guide() { path p; - pair uty, tip_distal, tip_proximal; - pair uty = dir(this.rest_angle+degrees(this.theta)); - tip_distal = this.tip_top + this.tip_height/3.0*uty; - tip_proximal = this.tip_top - this.tip_height/3.0*uty; - p = this.tip -- tip_distal -- tip_proximal -- cycle; + p = this.tip -- this.tip_distal -- this.tip_proximal -- cycle; return p; } guide arm_guide() { path p; - pair uy, uty, tip_distal, tip_proximal; - pair uy = dir(this.rest_angle); - pair ux = dir(this.rest_angle+90); - pair uty = dir(this.rest_angle+degrees(this.theta)); - tip_distal = this.tip_top + this.tip_height/3.0*uty; - tip_proximal = this.tip_top - this.tip_height/3.0*uty; if (this.dx == 0) { - p = tip_distal -- tip_proximal -- this.base; // should be colinear + // all three points should be colinear + p = this.tip_distal -- this.tip_proximal -- this.base; } else { - p = tip_distal -- tip_proximal{-uty} .. tension 0.75 .. {-uy}this.base; + p = this.tip_distal -- this.tip_proximal{-this.uty} + .. tension 0.75 .. {-this.uy}this.base; /* real angle_tip_proximal, angle_base; pair center = this.base + this.r_curve*dx; angle_tip_proximal = angle(tip_proximal - center); @@ -105,7 +114,7 @@ struct Cantilever { return p; } - void operator init (pair base=(0,0), real arm_length=2.5cm, real tip_height=0.5cm, real rest_angle=185, real dx=0) { + void operator init (pair base=(0,0), real arm_length=2.5cm, real tip_height=0.5cm, real rest_angle=195, real dx=0) { this.base = base; this.arm_length = arm_length; this.tip_height = tip_height; @@ -154,6 +163,74 @@ struct Substrate { } } +struct Photodiode { + pair center; + real radius = 8pt; + real x_scale = 0.5; + + void draw(pen fillpen=grey, pen drawpen=defaultpen) { + pair c = this.center; + pair y = (0, this.radius); + pair x = (this.x_scale*this.radius, 0); + filldraw(shift(this.center)*xscale(this.x_scale)*scale(this.radius) + *unitcircle, fillpen, drawpen); + draw((c-x)--(c+x)--c--(c-y)--(c+y), drawpen); + } + + void operator init(pair center=(0,0)) { + this.center = center; + } +} + +// extension() added sometime between asy v1.40 and v1.91 +pair extension(pair P, pair Q, pair p, pair q) +{ + pair ac=P-Q; + pair bd=q-p; + real det=ac.x*bd.y-ac.y*bd.x; + if(det == 0) return (infinity,infinity); + return P+((p.x-P.x)*bd.y-(p.y-P.y)*bd.x)*ac/det; +} + +struct Laser { + pair start; + real width = 2pt; // width at start (the laser source) + real spot = 1pt; // width at the cantilever reflection point (minimum) + pair dir; + Cantilever cantilever; + Photodiode photodiode; + + void draw(pen fillpen=red) { + pair w = scale(this.width/2)*rotate(90)*this.dir; + pair rw = scale(this.spot/2)*this.cantilever.uty; + if (dot(w, rw) < 0) rw = -rw; // ensure similar direction + // find point of reflection off cantilever. + pair ref = extension(this.start, this.start+this.dir, + this.cantilever.tip_distal, + this.cantilever.tip_proximal); + // find direction of reflection post-cantilever + pair post_dir = reflect((0,0), this.cantilever.uty)*dir; + pair contact = extension(ref, ref+post_dir, + this.photodiode.center, + this.photodiode.center+N); + real contact_width = this.width; ///length(ref-this.start)*length(ref-contact); + pair cw = scale(contact_width)*rotate(90)*post_dir; + if (dot(cw, rw) < 0) cw = -cw; // ensure similar direction + // laser -> cant. + fill((start+w)--(start-w)--(ref-rw)--(ref+rw)--cycle, fillpen); + // cant. -> photo. + fill((contact+cw)--(contact-cw)--(ref-rw)--(ref+rw)--cycle, fillpen); + } + + void operator init(pair start, pair dir=S, Cantilever cantilever, + Photodiode photodiode) { + this.start = start; + this.dir = unit(dir); + this.cantilever = cantilever; + this.photodiode = photodiode; + } +} + void distance(Label L, pair start, pair end) { pair center = (start+end)/2; pair u = unit(end-start); diff --git a/tex/src/figures/schematic/unfolding.asy b/tex/src/figures/schematic/unfolding.asy index bc70205..abfd490 100644 --- a/tex/src/figures/schematic/unfolding.asy +++ b/tex/src/figures/schematic/unfolding.asy @@ -147,7 +147,7 @@ draw(c.arm_guide(), grey); c.set_tip_for_dx(12pt); filldraw(c.tip_guide(), fillpen=black); draw(c.arm_guide(), black); -label("Cantilever", c.base-(0,10pt), SW); +label("Cantilever", c.base-(0,16pt), SW); Substrate s = Substrate(); s.draw(dir=S); -- 2.26.2