-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharrow.mp
153 lines (134 loc) · 4.45 KB
/
arrow.mp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
% -*-Fundamental-*-
% arrow.mp
% Add `arrowsimple' and `dblarrowsimple' commands that are like Hobby's
% arrow commands but do not fill in their arrowheads.
% 2000-Oct-22 Jim Hefferon [email protected]
% Jan-14 JH Went with perp lines
newinternal ahsimplelength, ahsimplewidth, ahsimpleangle;
% pick up Hobby's if none other specified
ahsimplelength := ahlength; % Hobby's default arrowhead length 4bp
ahsimpleangle := ahangle; % and default head angle 45 degrees
% Remark: I like 15 degrees and 2.5 pts for a start.
%ahsimplewidth := 1pt % width of fat end of arrowhead
% arrowheadsimple
% ARGS
% p The path, the end (highest time) of which will get an arrow
% RETURNS
% the arrowhead to place at the end of p
% METHOD
% Erect a number of line segs perp to the end of p, and draw arrowhead
% through them.
% The segs are regularly spaced in dist from the endpoint of p (taking the
% p-time poroved to make them very noticably not evenly spaced). The
% lengths of the segments falls quadratically, giving them a curve.
%
vardef arrowheadsimple expr p =
save q,e; path q; pair e;
save jtime,m,r,s,x; path m[],r,s[]; numeric x,jtime[];
if (ahsimplewidth <= 0pt):
ahsimplewidth := 2*(ahsimplelength*sind(0.5*ahsimpleangle)/cosd(0.5*ahsimpleangle)); % width of fat end of arrowhead
fi
e = point length p of p; r = p shifted -e;
forsuffixes x=1,.66,.33:
s[x] = makepath(pencircle scaled (2*x*ahsimplelength));
jtime[x] = xpart(r intersectiontimes s[x]);
m[x] = perp_line_to_path(r,2*x*x*ahsimplewidth,jtime[x]);
endfor
q = point 1 of m[1] .. point 1 of m[.66] .. point 1 of m[.33] .. (0,0)
& (0,0) .. point 0 of m[.33] .. point 0 of m[.66] .. point 0 of m[1];
q shifted e
enddef;
% perp_line_to_path
% returns a line of specified length perp to path at specified path-time
%
def perp_line_to_path(expr pth,lgth,pth_tme) =
((0,-.5lgth)--(0,.5lgth)) rotated angle(direction pth_tme of pth) shifted point pth_tme of pth
enddef;
% these are Hobby's with a `simp' added
path _asimpth;
def drawarrowsimple expr p = _asimpth:=p; _finarrsim enddef;
def drawdblarrowsimple expr p = _asimpth:=p; _findarrsim enddef;
def _finarrsim text t =
draw _asimpth t;
draw arrowheadsimple _asimpth t
enddef;
def _findarrsim text t =
draw _asimpth t;
draw arrowheadsimple _asimpth withpen currentpen t;
draw arrowheadsimple reverse _asimpth withpen currentpen t
enddef;
% cutasimple
% draw an arrow and return a point halfway through the arrow
% ARGS
% a, b two points previously specified as boxit suffixes
% p a path intersecting a's and b's bpath (e.g., probably
% this path goes through a.c and b.c, the centers of a's box and
% b's box)
% RETURNS
% a point on the arrow halfway from a to b
% COMMENTS
% from the MetaPost manual p. 60
vardef cutasimple(suffix a,b) expr p =
save q; path q;
q = p cutbefore bpath.a cutafter bpath.b;
drawarrowsimple q;
point .5*length q of q
enddef;
%=============================================================
% Action Arrows
%
% Acts like LaTeX's \mapsto: |---->
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
newinternal eraser_width;
eraser_width := 1.5pt;
def action_arrow(expr p) =
begingroup
interim ahsimplelength := 4pt;
interim ahsimplewidth := 1.5pt;
interim ahsimpleangle := 2*angle(ahsimplewidth,ahsimplelength);
% clear out background first
save currentpen; pen currentpen; currentpen = pencircle scaled eraser_width;
drawarrowsimple(p) withcolor white;
draw perp_line_to_path(p,2*ahsimplewidth,0) withcolor white;
save currentpen; pen currentpen; currentpen = pencircle scaled 0.4pt;
% now draw it
drawarrowsimple(p);
interim linecap:=butt;
draw perp_line_to_path(p,2*ahsimplewidth,0);
endgroup
enddef;
numeric _action_rad; _action_rad = 8pt; % radius is ahlength
def draw_action_arrow(expr p) =
save c; path c; c = fullcircle scaled _action_rad;
save s, f; numeric s, f;
(s,whatever) = p intersectiontimes (c shifted (point 0 of p));
(f,whatever) = p intersectiontimes (c shifted (point infinity of p));
save short_path; path short_path; short_path = subpath(s,f) of p;
action_arrow(short_path);
enddef;
%---------- length labellers ----------
%
% drawarrow_withticks
% Like this: |<----- label ----->|
%def drawarrow_withticks(expr pth,lbl) =
% begingroup
% save midpt; pair midpt; midpt = point .5 of pth;
% save lbl_pic; pic lbl_pic; lbl_pic = thelabel(btex etex,midpt);
%
% endgroup
%enddef;