Draw Laser and Photodiode in AFM schematic.
authorW. Trevor King <wking@drexel.edu>
Thu, 18 Feb 2010 20:35:53 +0000 (15:35 -0500)
committerW. Trevor King <wking@drexel.edu>
Thu, 18 Feb 2010 20:35:53 +0000 (15:35 -0500)
tex/src/figures/schematic/Makefile
tex/src/figures/schematic/afm.asy [new file with mode: 0644]
tex/src/figures/schematic/base_afm.asy
tex/src/figures/schematic/unfolding.asy

index 2f440a6c4e2e40e83cc2de8a301fb947a2c5e29e..7cf657c22b617258476fd10beac37c8f2993a911 100644 (file)
@@ -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 (file)
index 0000000..432bdbb
--- /dev/null
@@ -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);
index 1859b86c9f9602008b8145f6e5ecc38ae2fe0907..e73f1275128d02cd383c17952b5495e187c150b9 100644 (file)
@@ -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) <dot> (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);
index bc702057bab6fcd5c1e7666c83708fe092238ba3..abfd490df9ac53c5f9a1b9f6c92cd65c25de6d16 100644 (file)
@@ -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);