Am 01.05.2020 um 10:26 schrieb Gerben Wierda <gerben.wierda@rna.nl>:
I have been looking at lmt_followtext and followtext to get typesetting done along a path. That works fine, except that in my case, I need the text to not be exactly on that path, I need it to hover slightly above tor below he path. Given that the path may have an unpredictable form, that means that all the glyphs need to be shifted a bit, there is no generic transfrom of the entire text string that will work,
Can’t you duplicate and shift the path, i.e. keep the original visible and make the copy that carries the text invisible? That’s what I would do in a graphical application, but I would be surprised if MP wouldn’t know a transformation for this purpose.
No, that is what I did in the example, fiddling, but there is no transformation that will work in all cases. E.g. on the left side of the bump, I need to go to the upper left, on the right side to the upper right. There is no single shift that helps me. Nor a scale rotation or shift combination. That could be managed by only going up (though the distance to the path would vary, on the sides the text would be very close or on the top it would be too far.)
There is an example, at the link below, of creating a parallel path that claims to cope with sharp bends in the original path. You might be able to adapt it?<https://therion.speleo.sk/wiki/metapost#shuttering_two_parallel_lines>
That looks great. I’m going to investigate.
That approach works fine. Example trial code:
\starttext
\startMPpage
vardef parallelpath (expr P, gap)=
% adapted from https://therion.speleo.sk/wiki/metapost#shuttering_two_parallel_lines
save pathlength, linegap, testdiameter, testpath, innerpath, newpoint, curlength, intersections, samplepoint, sampledir, accuracy;
% work out a parallel path
% the easy way is to sample direction every few units, and add a parallel point into a new path
% however, this causes weird loops at sharp corners, so check if a sharp corner is coming up within
% the length of the gap between lines, and ignore that point if so
pathlength:=arclength P;
linegap:=gap;
accuracy:=2;
testdiameter:=linegap;
path testpath;
testpath:=(halfcircle rotated 180) scaled testdiameter;
pair newpoint;
pair sampledir;
path innerpath;
pair intersections;
curlength:=0;
forever:
samplepoint:=arctime curlength of P;
sampledir:=direction samplepoint of P;
newpoint:=((point samplepoint of P) shifted (linegap * unitvector(sampledir rotated -90)));
if curlength = 0:
innerpath:=newpoint{sampledir};
fi
% every now and then along the line, place a semicircle, rotated to face away from the line, offset by the thickness of the line,
% with a radius the same as the gap between the lines - if its ends touch the main line's centre, the corner is too sharp to use
% this point
save truetestpath; path truetestpath; truetestpath := (testpath rotated (angle sampledir) shifted (point samplepoint of P));
intersections:=P intersectiontimes truetestpath;
% if there are no intersections, intersectiontimes returns (-1,-1), otherwise it returns the distance along each path (P,testpath)
% where the intersection happened >=0
if (xpart intersections) = -1:
show "ADDED", newpoint{sampledir};
innerpath:=innerpath .. newpoint{sampledir};
else:
show "REJECTED", newpoint{sampledir};
draw truetestpath withcolor green withtransparency (1,0.1);
fi;
exitif curlength = pathlength;
% move in small steps, to take account of tight backwards curves, and to get points near a corner
curlength:=curlength + testdiameter/accuracy;
if curlength > pathlength:
curlength:=pathlength;
fi;
endfor;
if known innerpath:
if cycle P:
innerpath:=innerpath .. cycle;
fi;
fi;
innerpath
enddef;
path testIn, testOut;
testIn := (0,0)..(100,50)..(50,100)..(130,0);
testOut := parallelpath( testIn, 2);
draw testIn withpen pencircle scaled 1;
%draw testOut withpen pencircle scaled 1 withcolor red;
draw lmt_followtext [
text = "How well does it work? {\it It works very well!} {\bf It looks good enough.}",
path = reverse testOut,
spread = false,
];
Going to work with it. Thanks again.
G