[metapost] Labeling an angle

John Kitzmiller jkitz at verizon.net
Wed Dec 27 20:06:25 CET 2006


mailanholgerpeters at web.de wrote:
> Hi,
>
> thanks for your help, but I'd rather have a sector of a circle drawn around it, as in:
> http://de.wikipedia.org/wiki/Bild:Vertical_angles.png
>
> Is there an easier way than to do hard-coded positioning of the circle and the label?
>
> Holger
>   
Holger, (I am new to mp and forums. Apologies if I break decorum and 
please advise.)

Use macros, either within the mp document, or stored  as a file to be 
used with  input.
 
Hobby's mpman (around page 45) and Heck's tutorial (pp 38 and 52 at 
least)  present macros for marking congruency. Links to both can be 
found at <<http://www.tug.org/metapost.html>>
Similar code snippets can be found among the many offerings of the mp 
giants listed on that page.

Below are copies+hacks which I put in a path for mp to access, in my 
case C:\texmf\metapost\base which can then be called with
input <filename>
at the beginning of the mp document(s). (None of this is clean, but it 
works for me.)

The first commented section, from Heck, uses multiple arcs to show angle 
congruency. I prefer tick-marks across one arc. One weakness in the code 
is that when all four vertical angles are marked one ends up with a 
circle where arcs of a slightly different radius might be preferable. I 
am sure this could be cobbled from the codes below. So far I have 
avoided that requirement.

%angle_radius := 4mm;
%angle_delta := 0.5mm;
%mark_size := 2mm;

% % --- draw 1, 2, 3 or 4 arcs ---
% def mark_angle(expr A, common, B, n) =
%     draw_angle(A, common, B, angle_radius);
%         if n>1: draw_angle(A, common, B,
%             angle_radius+angle_delta); fi;
%         if n>2: draw_angle(A, common, B,
%             angle_radius-angle_delta); fi;
%         if n>3: draw_angle(A, common, B,
%             angle_radius+2*angle_delta); fi;
% enddef;
%
% def draw_angle(expr endofa, common, endofb, r) =
% begingroup
% save tn;
% tn := turningnumber(common--endofa--endofb--cycle);
% draw (unitvector(endofa-common){(endofa-common)
% rotated(tn*90)} .. unitvector(endofb-common))
% scaled r shifted common;
% endgroup
% enddef;

% -- arcs with ticks for angles --
marksize=4pt;
angle_radius:=8pt;

def draw_mark(expr p, a) =
  begingroup
  save t, dm; pair dm;
  t = arctime a of p;
  dm = marksize*unitvector direction t of p
    rotated 90;
  draw (-.5dm.. .5dm) shifted point t of p;
  endgroup
enddef;

def draw_marked(expr p, n) =
  begingroup
  save amid;
  amid = .5*arclength p;
  for i=-(n-1)/2 upto (n-1)/2:
    draw_mark(p, amid+.6marksize*i);
  endfor
  draw p;
  endgroup
enddef;

def mark_angle(expr a, b, c, n) =
  begingroup
  save s, p; path p;
  p = unitvector(a-b){(a-b)rotated 90}..unitvector(c-b);
  s = .9marksize/length(point 1 of p - point 0 of p);
  if s<angle_radius: s:=angle_radius; fi
  draw_marked(p scaled s shifted b, n);
  endgroup
enddef;  

% --- right angle mark ---
def mark_rt_angle(expr endofa, common, endofb) =
begingroup
    save tn; tn :=
    turningnumber(common--endofa--endofb--cycle);
    draw ((1,0)--(1,1)--(0,1)) zscaled(mark_size*
    unitvector((1+tn)*endofa+(1-tn)*endofb-2*common))
    shifted common;
endgroup
enddef;

% --- tick marks ---
def tick(expr p, n) =
begingroup
    save midpnt;
    midpnt = 0.5*arclength(p);              % find the time when 
half-way the path
    for i=-(n-1)/2 upto (n-1)/2:
    draw_mark(p, midpnt+mark_size*i/2);     % place n tick marks
    endfor;
endgroup
enddef;

def draw_mark(expr p, m) =
begingroup
save t, dm; pair dm;
t = arctime m of p;                                         % find a 
vector orthogonal to p at time t
dm = mark_size*unitvector(direction t of p rotated 90);
draw(-1/2dm..1/2dm) shifted (point t of p);                 % draw tick mark
endgroup
enddef;

 % --- parallel marks ---
 def para(expr p, n) =
 begingroup
     save midpnt;
     midpnt = 0.5*arclength(p);              % find the time when 
half-way the path
     for i=-(n-1)/2 upto (n-1)/2:
     draw_para(p, midpnt+mark_size*i/2);     % place n para marks
     endfor;
 endgroup
 enddef;

 def draw_para(expr p, m) =
 begingroup
 save t, dm, mm; pair dm, mm;
 t = arctime m of p;                                             % find 
a vector orthogonal to p at time t
     dm = mark_size*unitvector(direction t of p rotated 90);
     mm = unitvector(direction t of p);
 draw(-.5dm--2.2*mm--.5dm) shifted (point t of p);               % draw 
para mark
 endgroup
 enddef;


For example:

input <macro>;
u:=50;
beginfig(1);
z0 = (0,0);
z1 = z0 - u*dir(20);
z2 = z0 + u*dir(20);
z3 = z0 - u*dir(152);
z4 = z0 + u*dir(152);
drawdblarrow z1--z2;
drawdblarrow z3--z4;
mark_angle(z3,z0,z2,0);
mark_angle(z4,z0,z1,0);
label.bot(btex $\theta$ etex,z0);
label.rt(btex $48^\circ$ etex,z0) shifted (9,0);
label.lft(btex $\alpha$ etex,z0) shifted (-7,0);
endfig;

Regards, with many thanks to the mp community,

John


More information about the metapost mailing list