# Metapost, rotation function not working

I am trying to rotate a vector by an angle as follows:

u:=2cm;

vardef rotate(expr p, t)=
x := xpart(p);
y := ypart(p);

(cosd(t)*x - sind(t)*y, sind(t)*x + cosd(t)*y)
enddef;

vardef line(expr pfirst, psecond)=
m := 0.2;
pair tangent, rv;
tangent := psecond - pfirst;
tx := xpart tangent;
ty := ypart tangent;
tangent := (-ty, tx);
numeric len;
len = sqrt(tx*tx + ty*ty);
tangent := tangent * 1/len;

rv := rotate(tangent, 0.01);

draw u*pfirst--u*psecond withpen pencircle scaled 1 withcolor black;
draw u*pfirst--u*(pfirst + rv * 0.15) withpen pencircle scaled 1 withcolor black;

draw u*(pfirst + tangent * m)--u*(psecond + tangent * m) withpen pencircle scaled 1 withcolor black;
enddef;


However the output is: That's a 90 degree angle, which is not at all what I was trying to calculate, and any other value that I pass to the macro looks exactly like this. The result should look like this diagram: • Could you describe a bit more what you would like the arguments to be, and what the output should be in relation to those? metapost has built in operators rotatedaround, dir and angle. The first rotates about a point through an angle. The second takes an angle as argument and returns a unitvector in that direction, and the third takes a vector as input and returns its angle as output. If you were aware of those, then disregard, but if not, then they likely could be used to get whatever your desired output is more simply. Feb 14, 2020 at 4:09
• Thanks to your comment I found about rotate Feb 14, 2020 at 4:29
• Ah yes, also just plain old rotated which rotates about the origin. To be clear: you want to pass two point, say leftmost and top, and have that diagram drawn? Feb 14, 2020 at 4:37
• Correct, bonus points if the vertices are labeled : p Feb 14, 2020 at 4:41
• Also, it would help if you posted a complete minimal example. That is to say, the complete MetaPost program that produces your error. As short as possible but something that we can execute out of the box.. Feb 14, 2020 at 5:27

This is my attempt. I made liberal use of rotatedabout both because it worked nicely, and because rotations led to your question. I couldn't think of a better way to get the arrows other than:

• take the line connecting node centers, and chop of the portions inside (undrawn) circles around the nodes in order to get some separation between the nodes and the arrows.
• take the resulting line and shift it some distance perpendicular to its direction in order to get separation between the forward and backward harpoons.
• rotate this line through an angle about its terminal point and travel back some distance to obtain the harpoon tip.
• rotate the result about the midpoint of the line connecting node centers to obtain the harpoon in the other direction \documentclass[border=5mm]{standalone}

\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\mplibnumbersystem{double}
\begin{mplibcode}
u:=2cm;

vardef harpoons(expr p,q,s,t)=
save a,k; path a[]; clearxy;
ang:=25; % ang = harpoon angle
k:=.07;  % k= length of harpoon
a0=fullcircle scaled s; % s = separation btw harpoon tip and node
a1=(p--q) cutbefore (a0 shifted p) cutafter (a0 shifted q); % chop path btw nodes at circles
z0=dir(angle(q-p)+90); % z0 = unitvector perpendicular to line through p and q
a2=a1 shifted (t*z0); % shift p--q perp dist along z0
% a3 = harpoon tip: rotate a2 about endpoint through ang, then move some dist along this line
a3=a2--k[point 1 of a2,point 0 of a2 rotatedabout(point 1 of a2,-ang)];
draw a3 withpen pencircle scaled 1bp;
% once we have one harpoon, the other is just a rotation of it
draw a3 rotatedabout(point .5 of a1,180) withpen pencircle scaled 1bp;
enddef;

% nsep=sep between node and harpoon, nsize= node size, psep=separation between harpoons
vardef dmnd(expr p,q,nsep,nsize,psep)=
clearxy;
z0=p; z1=q;