CSS

Showing posts with label Metapost. Show all posts
Showing posts with label Metapost. Show all posts

Tuesday, February 21, 2012

Metapost and Labels

This is just a quick note to myself. When I want to write a label with a smaller font, I should use \scriptstyle...but it is tricky since it requires math mode!

So an example, consider this diagram describing an experiment for gravitational redshift:

numeric u;
u = 1pc;
beginfig(0)
  path earth;
  pair clock[];

  earth = fullcircle scaled u;

  clock[0] = (0,2u);
  clock[1] = (0,4u);

  draw (0,0)--(0,5u) dashed evenly;

  for i=0 upto 1:
    label(btex $\bullet$ etex, clock[i]);
  endfor;

  fill earth withcolor 0.75white;
  draw earth;
  label.rt(btex ${\scriptstyle\rm Earth}$ etex, (.5u,0));
  label.rt(btex ${\scriptstyle\rm Satellite\ 1}$ etex, clock[0]);
  label.rt(btex ${\scriptstyle\rm Satellite\ 2}$ etex, clock[1]);
endfig;
end;

Just remember to use "\ " for spaces. Otherwise it will all run together horribly!

Saturday, December 24, 2011

My Differential Geometry Images

So I am writing some notes on differential geometry, and using metapost for tricky diagrams. Here are a few of the tricky diagrams I have.

The first three images are:

The third image is a tad bit bigger:

Note the fonts in this picture are messed up, since I had to use postscript fonts. It looks far more beautiful in TeX using metapost, trust me!

numeric u;
color yellow;
u := 1pc;
yellow = red+green;

verbatimtex \input amssym.tex etex;

% sphere
beginfig(0)
  draw fullcircle scaled 4u;
  draw (-2u,0)..(0,-.7u)..(2u,0);
  draw (-2u,0)..(0,.7u)..(2u,0) dashed evenly;
endfig;

% plane + cylinder
beginfig(1)
  draw (0,-u)--(0,3u)--(u,4u)--(u,0)--cycle;

  draw (3u,0)..(4u,-.5u)..(5u,0);
  draw (3u,0)..(4u,.5u)..(5u,0) dashed evenly;

  draw (3u,4u)..(4u,4.5u)..(5u,4u);
  draw (5u,4u)..(4u,3.5u)..(3u,4u);

  draw (3u,0)--(3u,4u);
  draw (5u,0)--(5u,4u);
endfig;

% saddle
beginfig(2)
  path p[];
  z[0] = (2u,4u);
  z[1] = (2.5u,3u);
  z[2] = (1.5u,2.5u);
  z[3] = (4u,0u);
  z[4] = (6.5u,u);
  z[5] = (7.u,1.75u);
  z[6] = (6.75u,0.5u);

  p[0] = z[0]..z[1]..z[2];
  p[1] = z[1]..z[3]..z[4];
  p[2] = z[5]..z[4]..z[6];

  p[3] = z[0]--(point 0.75*length(p[1]) of p[0]);
  p[4] = z[2]--(1.75u,-2u);
  p[5] = z[6]--(6.5u,-2u);
  p[6] = z[5]--(point 0.9*length(p[1]) of p[2]);
  for i=0 upto 6:
    draw p[i];
  endfor;

  draw (4u,-u){up}..(point 0.6*length(p1) of p1);
  draw (point 0.6*length(p1) of p1)..{down}(5.125u,-.75u) dashed evenly;
  draw (1.75u,-2u)..(4u,-u)..(6.5u,-2u);

  p7 = ((0,0)--(2u*unitvector(direction 0 of p[6]))) shifted point (length p6) of p[6];
  draw p[7] dashed evenly;

  p8 = ((0,0)--(3.5u*unitvector(direction 0 of p3))) shifted point (length p3) of p3;
  draw p8 dashed evenly;

  p9 = (point (length p8) of p8)..(5.125u,-.75u)..(point (length p7) of p7);
  draw p9 dashed evenly;

endfig;

beginfig(3)
  picture Rn;
  picture sphere;
  picture torus;
  % R^n
  Rn = image(
      for i=1 upto 3:
      draw (-.5u,i*u)--(3.5u,i*u) withcolor 0.75white;
      draw (i*u,-.5u)--(i*u,3.5u) withcolor 0.75white;
    endfor;
    drawdblarrow (-.5u,0)--(3.5u,0);
    drawdblarrow (0,-.5u)--(0,3.5u);
    );
  % sphere  
  sphere = image( 
      draw fullcircle scaled 4u;
    draw ((-2u,0)..(0,-.7u)..(2u,0));
    draw ((-2u,0)..(0,.7u)..(2u,0)) dashed evenly;
    );
  % torus
  torus = image(
      path hole;
    path uhole;
      draw
      (0,2u)..(-2u,0)..(0,-2u)..(2u,-u)..(4u,-2u)..(6u,0)..(4u,2u)..(2u,u)..cycle;
    hole = halfcircle rotated 180 scaled 2u shifted (4.5u,0);
    draw hole;
    uhole = (point 0.1*length(hole) of hole)
     ..(0.5[(point 0.1*length(hole) of hole),(point 0.9*length(hole) of hole)]+(0,.5u))
     ..(point 0.9*length(hole) of hole);
    draw uhole; 
    );
  
  draw Rn;
  draw Rn shifted (20u,-5u);

  draw torus shifted (8u,4u);

  path localPatch;
  path imageOfF;
  path preimageOfG;
  path imageOfG;
  path imageOfPsi;
  path intersection;
  localPatch = (fullcircle scaled 2u shifted (1.5u,1.5u));
  fill localPatch withcolor 0.75[blue,white];
  draw localPatch dashed evenly;

  z[0] = (((u,0)--(u,2u)) intersectionpoint localPatch);
  draw (((0,u)--(u,u)) intersectionpoint localPatch)
  --(((2u,u)--(4u,u)) intersectionpoint localPatch) withcolor 0.75[black,blue];
  draw (((0,2u)--(2u,2u)) intersectionpoint localPatch)
  --(((2u,2u)--(4u,2u)) intersectionpoint localPatch) withcolor 0.75[black,blue];
  draw (((u,0)--(u,2u)) intersectionpoint localPatch)
  --(((u,2u)--(u,4u)) intersectionpoint localPatch) withcolor 0.75[black,blue];
  draw (((2u,0)--(2u,2u)) intersectionpoint localPatch)
  --(((2u,2u)--(2u,4u)) intersectionpoint localPatch) withcolor 0.75[black,blue];

  imageOfF = fullcircle xscaled 3u yscaled 1.5u shifted (8u,4u);
  fill imageOfF withcolor 0.75[blue,white];
  draw imageOfF dashed evenly;

  picture preG;

  preG = image(
  
  preimageOfG = unitsquare scaled 2u rotated 45 shifted (22u,-5u);

    fill preimageOfG withcolor 0.5[yellow,white];
    fill fullcircle xscaled u yscaled 5u rotated -23 shifted (22u,-3u)
      withcolor 0.5[green,white];
      draw (((21u,-4u)--(21u,-5u)) intersectionpoint preimageOfG)
    --(((21u,-5u)--(21u,-3u)) intersectionpoint preimageOfG)
    withcolor 0.5[black,yellow];
  draw (((22u,-2u)--(22u,-3u)) intersectionpoint preimageOfG)
    --(((22u,-4u)--(22u,-8u)) intersectionpoint preimageOfG)
    withcolor 0.5[black,yellow];
  draw (((23u,-3u)--(23u,-3.5u)) intersectionpoint preimageOfG)
    --(((23u,-3.5u)--(23u,-8u)) intersectionpoint preimageOfG)
    withcolor 0.5[black,yellow];
  draw (((21u,-4u)--(22u,-4u)) intersectionpoint preimageOfG)
    --(((22u,-4u)--(25u,-4u)) intersectionpoint preimageOfG)
    withcolor 0.5[black,yellow];
  draw (((21u,-3u)--(22u,-3u)) intersectionpoint preimageOfG)
    --(((22u,-3u)--(25u,-3u)) intersectionpoint preimageOfG)
    withcolor 0.5[black,yellow];
  draw preimageOfG dashed evenly;

  clip currentpicture to preimageOfG;
    );
  draw preG;

  imageOfG = (19u,2.5u)--(20u,3u)--(21.5u,3u)--(21u,2.5u)--cycle;


  fill imageOfG withcolor 0.5[white,yellow];

  imageOfPsi = fullcircle xscaled 2u yscaled u rotated -45
    shifted (20u,3u);
  fill imageOfPsi withcolor 0.75[blue,white];


  numeric t[];
  (t[0],whatever) = imageOfPsi intersectiontimes ((19u,2.5u)--(20u,3u));
  (t[1],whatever) = imageOfPsi intersectiontimes ((21u,2.5u)--(19u,2.5u));
  (t[2],whatever) = imageOfPsi intersectiontimes ((20u,3u)--(23u,3u));  
  (t[3],whatever) = imageOfPsi intersectiontimes ((19u,2.5u)--(20u,2.5u));
  
  intersection = (subpath(t0,t3) of imageOfPsi)--%(20u,3u)--
    (subpath(t1,t2) of imageOfPsi)--(20u,3u)--cycle;
  
  fill intersection withcolor 0.5[green,white];
  draw imageOfPsi dashed evenly;
  draw imageOfG dashed evenly;
  draw sphere shifted (20u,4u);

  p[0] := (point 0.25*length(localPatch) of localPatch)..(4u,4u)
  ..(point 0.5*length(imageOfF) of imageOfF);
  p[1] := (point 0 of imageOfF)..(12u,5u)..(19.5u,3.5u);
  p[2] := (21.5u,3u)..(23u,0)..(23u,-3u);
  p[3] := (point .75*length(localPatch) of localPatch)..(1.5u,-u)
  ..(10u,-4u)..(21.5u,-4.5u);
  drawarrow p[0];
  
  drawarrow p1;

  drawarrow p2;

  drawarrow p3 dashed evenly;

  label.top(btex $x$ etex, point 0.5*length(p0) of p0);
  label.top(btex $\varphi$ etex, point 0.75*length(p1) of p1);
  label.rt(btex $y^{-1}$ etex, point 0.5*length(p2) of p2);
  label.bot(btex $y^{-1}\circ\varphi\circ x$ etex, point 0.6*length(p3) of p3);

  label(btex $U$ etex, (1.5u,1.5u)) withcolor 0.5[black,blue];

  draw (8u,4u) withpen pencircle scaled 3;
  label.lft(btex $p$ etex, (8u,4u)) withcolor 0.75[blue,black];
  label.bot(btex $M$ etex, (12u,2u));

  label.rt(btex $N$ etex, (22u,4u));

  label.lft(btex $\Bbb{R}^{n}$ etex, (20u,-2u));

  label.lft(btex $\Bbb{R}^{m}$ etex, (0,3u));
endfig;


end;

Thursday, December 15, 2011

MetaPost, Plotting, and numerical precision

So, to write up diagrams in LaTeX, you need to use Metapost. But Metapost doesn't use floating point arithmetic.

As Claudio Beccari's "Floating point numbers and METAFONT, METAPOST, TEX, and PostScript Type 1 fonts" (TUGboat [pdf]) notes, 32 bit integers are used to represent real numbers. The first 16 bits form the fractional part, 14 bits the integer part, 1 bit for the sign, and 1 bit for special purposes.

So, that means we have 16 log(2)/log(10) digits of precision, or about 4 digits. Now lets remember:

1 PS point = 1.00375 points
1 pica = 12 PS points
1 inch = 72 PS points = 72.27 points = 6 pica
1 cm = 28.3464567 PS points = 2.36220472 pica

We have precision of 2-16 points, or about 0.000868055556 inches, or 0.00220486111 centimeters.

That's decent for output but not for intermediate computations. For example, if we were to plot xx, we may lose a lot of precision.

Plots in Metapost

Lets consider a simple plot of $f(x)=x^{2}$.

numeric u;
u := 1pc; % units

vardef f(expr x) = x*x enddef;

beginfig(0)
  % draw the axes
  drawdblarrow (-3u-ahlength,0)--(3u+ahlength,0);
  drawdblarrow (0,0-2ahlength)--(0,9u+ahlength);

  % plot the function
  draw (-3u,f(-3)*u)
    for i=-3+0.05 step 0.05 until 3:
    ..(i*u,f(i)*u)
  endfor;
endfig;
end;

Remember that ahlength is the length of the arrow head.

This basic scheme can be generalized if we add numerics x0 and x1 which control where the plot begins and ends (respectively), as well as the step size dx which is taken to be "small enough".

Revising our code:

numeric u;
numeric dx;
u := 1pc; % units
dx := 0.05; 

vardef f(expr x) = x*x enddef;

beginfig(0)
  numeric x[];

  x0 := -3; % start plotting at x=-3
  x1 := 3; % stop plotting at x=+3

  % draw the axes
  drawdblarrow (x0*u-ahlength,0)--(x1*u+ahlength,0); % x-axis
  drawdblarrow (0,0-2ahlength)--(0,f(x1)*u+ahlength); % y-axis

  % plot the function
  draw (x0*u,f(x0)*u)
    for i=x0+dx step dx until 3:
    ..(i*u,f(i)*u)
  endfor;
endfig;
end;

This makes things a little complicated. What we are doing is computing the pairs (x,y) and then scaling them, then plotting.

The dx is the change in x before scaling. The points plotted have a change in x that amounts to dx*u=0.6pt approximately.

But we can do more! If we specify how big we want this plot to be, i.e. it has to fit within X inches, then we can determine the scale u by this.

Specifically, u := X/(x[1]-x[0]) is the scale factor definition.

If we demand that dx*u=0.6pt hold, which is "sufficiently good" for practical purposes, then we also define dx := (3pt)/(5*u).

The interested reader may want to read Learning Metapost by Doing.