It does not seem to work for all character combinations. e.g. B&T works, C&T works, C&M works, but N&T does not work. not N&M Why would that be? Thanks .Floris
On 22 Sep 2018, at 11:27, Hans Hagen
wrote: On 9/22/2018 10:35 AM, Henri Menke wrote:
Dear list, Challanged by a very old TeX.SX question https://tex.stackexchange.com/questions/180510 I wanted to calculate all the intersection points between two characters. Therefore I ripped off the \showshape macro to load the outlines from the font and convert them to MetaPost paths. Then I try to find all intersections by cutting the path. It somewhat works but for some reason, in the MWE below two intersection points are missing. I also have the feeling that my implementation is extremely inefficient. I would very much appreciate some hints by the MetaPost experts! Cheers, Henri --- \startluacode -- That's a simple reimplemetation of the showshape macro function outlinepaths(character) local fontid = font.current() local shapedata = fonts.hashes.shapes[fontid] -- by index local chardata = fonts.hashes.characters[fontid] -- by unicode local shapeglyphs = shapedata.glyphs or { } character = utf.byte(character) local c = chardata[character] if c then if not c.index then return {} end local glyph = shapeglyphs[c.index] if glyph and (glyph.segments or glyph.sequence) then local units = shapedata.units or 1000 local factor = 100/units local paths = fonts.metapost.paths(glyph,factor) return paths end end end \stopluacode \def\mpdefineoutlines#1#2{\ctxlua{ local char = "\luaescapestring{#1}" local outlines = outlinepaths("#2") local len = \letterhash outlines tex.print("path " .. char .. "[];") tex.print(char .. "n := " .. len .. ";") for i, path in ipairs(outlines) do tex.print(char .. "[" .. i .. "] := " .. path .. ";") end }} \starttext \startMPpage pair shift; shift := (1cm,-1cm); numeric angle; angle := 5; \mpdefineoutlines{B}{B} \mpdefineoutlines{T}{T} nofill B2; nofill B3; eofill B1 withcolor .5[blue,white]; fill T1 shifted (shift) rotated (angle) withcolor .5[red,white]; path r; numeric n; n := 0; for i = 1 upto Bn: for j = 1 upto Tn: r := B[i]; forever: pair q; r := r cutbefore (T[j] shifted (shift) rotated (angle)); exitif length cuttings = 0; r := subpath(epsilon, length r) of r; q = point 0 of r; n := n + 1; dotlabel.urt(textext("\tfx" & decimal n), q); endfor; endfor ; endfor ; \stopMPpage \stoptext
You migh find more when you go top double mode .. anyway, these intersection calculations are not that accurate so you normally need to apply some overkill.
- a bit cleaned up outlinepath function - use document namespace - add helper for defineoutline - do 4 runs over the shapes (probably too many now) - more neutral fill code
It makes a nice example for the metafun (although then I'd do it slightly different). We need some rounding becaus eotherwise you get similar points (you can add a message(q) someplace).
\startluacode
function document.outlinepaths(character) local chardata = fonts.hashes.characters[true] -- by unicode local shapedata = fonts.hashes.shapes[true] -- by index local c = chardata[character] if c and c.index and shapedata then local shapeglyphs = shapedata.glyphs or { } local glyph = shapeglyphs[c.index] if glyph and (glyph.segments or glyph.sequence) then local units = shapedata.units or 1000 local factor = 100/units return fonts.metapost.paths(glyph,factor) end end return { } end
function document.defineoutline(char,target) local outlines = document.outlinepaths(char) local nofpaths = #outlines context("path %s[] ;",target) context("numeric %sn ; %sn := %s ;",target,target,nofpaths) for i=1,nofpaths do context("%s[%i] := %s ; ",target,i,outlines[i]) end end \stopluacode
\def\mpdefineoutlines#1#2{\ctxlua{document.defineoutline(\number`#1,"#2")}}
\starttext
\startMPpage pair shift ; shift := (1cm,-1cm); numeric angle ; angle := 5;
\mpdefineoutlines{B}{B} \mpdefineoutlines{T}{T}
for i=1 upto Bn - 1 : nofill B[i] ; endfor ; eofill B[Bn] withcolor .5[blue,white] ;
for i=1 upto Tn : T[i] := T[i] shifted shift rotated angle ; endfor ;
for i=1 upto Tn - 1 : nofill T[i] ; endfor ; eofill T[Tn] withcolor .5[red,white] ;
pair found[] ; boolean isnew ; numeric n ; n := 0 ; pair rq ;
def GoForIt(expr how) = path r ; for i = 1 upto Bn : for j = 1 upto Tn : r := B[i] ; forever: pair q ; if how = 1 : r := r cutbefore T[j] ; elseif how = 2 : r := r cutbefore reverse T[j] ; elseif how = 3 : r := reverse r cutbefore T[j] ; else : r := reverse r cutbefore reverse T[j] ; fi ; exitif length cuttings = 0 ; r := subpath(epsilon, length r) of r ; q = point 0 of r ; isnew := true ; rq := round(q); for f=1 upto n : if found[f] = rq : isnew := false ; exitif true ; fi ; endfor ; if isnew : n := n + 1 ; drawdot q withpen pencircle scaled 4 ; draw textext("\strut\ttbf " & decimal n) ysized 3 shifted q withcolor white ; found[n] := rq ; fi ; endfor; endfor ; endfor ; enddef ;
for i=1 upto 4 : GoForIt(i) ; endfor ;
\stopMPpage
\stoptext
--
----------------------------------------------------------------- Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl ----------------------------------------------------------------- ___________________________________________________________________________________ If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context webpage : http://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : http://contextgarden.net ___________________________________________________________________________________