[NTG-context] Metafun: Finding intersection between characters

Floris van Manen vm at klankschap.nl
Sat Sep 22 12:08:34 CEST 2018


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 <j.hagen at xs4all.nl> 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 at 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
> ___________________________________________________________________________________

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.ntg.nl/pipermail/ntg-context/attachments/20180922/5e1e0c73/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screen Shot 2018-09-22 at 12.04.54.PNG
Type: image/png
Size: 17676 bytes
Desc: not available
URL: <http://mailman.ntg.nl/pipermail/ntg-context/attachments/20180922/5e1e0c73/attachment-0001.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://mailman.ntg.nl/pipermail/ntg-context/attachments/20180922/5e1e0c73/attachment-0001.sig>


More information about the ntg-context mailing list