FilledCurve curve specification

Dear all,

During playing with ImportString and ExportString and using outlines I found that FilledCurve can be called with two arguments as in:

Graphics@FilledCurve[{{{0,2,0},{0,1,0},{1,3,3},{1,3,3},{1,3,3},{1,3,3},{0,1,0},{1,3,3},{1,3,3},{0,1,0},{0,1,0},{0,1,0},{1,3,3},{1,3,3},{0,1,0},{1,3,3},{1,3,3},{0,1,0},{1,3,3},{1,3,3},{1,3,3},{1,3,3},{0,1,0},{1,3,3},{1,3,3},{0,1,0}},{{0,2,0}}},{{{0.20249999999999996`,8.4205`},{1.8224999999999998`,8.4205`},{1.8224999999999998`,5.505871093750001`},{1.8224999999999998`,5.332550802707672`},{1.8421874570846555`,5.205460958957673`},{1.8815624999999998`,5.1246015625000005`},{1.9501171874999996`,4.981867208957673`},{2.0858202695846555`,4.910500000000001`},{2.2886718749999995`,4.910500000000001`},{2.417695226669311`,4.910500000000001`},{2.544082117080688`,4.954093760728837`},{2.6678320312499997`,5.041281250000001`},{2.738847570419311`,5.089093728542329`},{2.828320398330688`,5.169249978542329`},{2.93625`,5.281750000000001`},{2.93625`,7.678`},{2.93625`,7.8731171875`},{2.9003906249999996`,8.009611413955689`},{2.8286718749999995`,8.087482421875`},{2.7569531249999994`,8.165353429794312`},{2.612812414169311`,8.208859289169311`},{2.3962499999999998`,8.218`},{2.3962499999999998`,8.4205`},{4.151249999999999`,8.4205`},{4.151249999999999`,5.3492500000000005`},{4.151249999999999`,5.155539041042329`},{4.183242101669311`,5.021681662082672`},{4.247226562499999`,4.9476777343750005`},{4.311211023330688`,4.873673838853836`},{4.436718578338622`,4.827531260728836`},{4.623749999999999`,4.8092500000000005`},{4.623749999999999`,4.60675`},{4.097460937499999`,4.55964062768221`},{3.7657617187499994`,4.525011718750001`},{3.6286523437499993`,4.502863281250001`},{3.4915429687499997`,4.48071484375`},{3.271992101669311`,4.4253437500000015`},{2.9699999999999998`,4.33675`},{2.9699999999999998`,4.910500000000001`},{2.766796789169311`,4.731906239271165`},{2.598398523330688`,4.6058710991144185`},{2.4648046874999996`,4.5323945312500005`},{2.231015539169311`,4.401964842408896`},{1.9875585937499998`,4.33675`},{1.7344335937499997`,4.33675`},{1.4588085508346555`,4.33675`},{1.2020800781249998`,4.424025390625001`},{0.9642480468749999`,4.598576171875001`},{0.7264160156249999`,4.773126953125001`},{0.6074999999999999`,5.083468750000001`},{0.6074999999999999`,5.529601562500001`},{0.6074999999999999`,7.678`},{0.6074999999999999`,7.879796789169312`},{0.5797265839576721`,8.01180859375`},{0.5241796874999999`,8.07403515625`},{0.468632823228836`,8.13626171875`},{0.3614062392711639`,8.18425`},{0.20249999999999996`,8.218`},{0.20249999999999996`,8.4205`}},{{2.3625`,8.52175`},{2.3625`,8.52175`}}}]

produces:


If we extract the real points and plot those, and use Line for the segment:

Graphics@FilledCurve[Line@{{0.20249999999999996`,8.4205`},{1.8224999999999998`,8.4205`},{1.8224999999999998`,5.505871093750001`},{1.8224999999999998`,5.332550802707672`},{1.8421874570846555`,5.205460958957673`},{1.8815624999999998`,5.1246015625000005`},{1.9501171874999996`,4.981867208957673`},{2.0858202695846555`,4.910500000000001`},{2.2886718749999995`,4.910500000000001`},{2.417695226669311`,4.910500000000001`},{2.544082117080688`,4.954093760728837`},{2.6678320312499997`,5.041281250000001`},{2.738847570419311`,5.089093728542329`},{2.828320398330688`,5.169249978542329`},{2.93625`,5.281750000000001`},{2.93625`,7.678`},{2.93625`,7.8731171875`},{2.9003906249999996`,8.009611413955689`},{2.8286718749999995`,8.087482421875`},{2.7569531249999994`,8.165353429794312`},{2.612812414169311`,8.208859289169311`},{2.3962499999999998`,8.218`},{2.3962499999999998`,8.4205`},{4.151249999999999`,8.4205`},{4.151249999999999`,5.3492500000000005`},{4.151249999999999`,5.155539041042329`},{4.183242101669311`,5.021681662082672`},{4.247226562499999`,4.9476777343750005`},{4.311211023330688`,4.873673838853836`},{4.436718578338622`,4.827531260728836`},{4.623749999999999`,4.8092500000000005`},{4.623749999999999`,4.60675`},{4.097460937499999`,4.55964062768221`},{3.7657617187499994`,4.525011718750001`},{3.6286523437499993`,4.502863281250001`},{3.4915429687499997`,4.48071484375`},{3.271992101669311`,4.4253437500000015`},{2.9699999999999998`,4.33675`},{2.9699999999999998`,4.910500000000001`},{2.766796789169311`,4.731906239271165`},{2.598398523330688`,4.6058710991144185`},{2.4648046874999996`,4.5323945312500005`},{2.231015539169311`,4.401964842408896`},{1.9875585937499998`,4.33675`},{1.7344335937499997`,4.33675`},{1.4588085508346555`,4.33675`},{1.2020800781249998`,4.424025390625001`},{0.9642480468749999`,4.598576171875001`},{0.7264160156249999`,4.773126953125001`},{0.6074999999999999`,5.083468750000001`},{0.6074999999999999`,5.529601562500001`},{0.6074999999999999`,7.678`},{0.6074999999999999`,7.879796789169312`},{0.5797265839576721`,8.01180859375`},{0.5241796874999999`,8.07403515625`},{0.468632823228836`,8.13626171875`},{0.3614062392711639`,8.18425`},{0.20249999999999996`,8.218`},{0.20249999999999996`,8.4205`}}]

we get:


So it is the same shape, but not smoothed.

So there are two undocumented things here: (1) The function FilledCurve also accepts segments without the head Line, BezierCurve, or BSplineCurve. (2) The function FilledCurve accepts two arguments for some cases.
I was hoping one of developers or people from the community could enlighten all of us what the integers mean in the first argument, and what the final product is (beziercurve? bspline?). And how can we control it?

Here’s the mapping for the triples in the first argument of FilledCurve:

commandToPrimitive[{type_, numPoints_, degree_}, pts_] := Switch[type, 
  0, Line[pts], 
  1, BezierCurve[pts, SplineDegree -> degree], 
  3, BSplineCurve[pts, SplineDegree -> degree]] 

where ‘pts’ is just consuming the second argument of FilledCurve sequentially.

You can apply the undocumented function GeometricFunctions`DecodeFilledCurve to any FilledCurve object to see the fully decoded form.

Related thread on Mathematica.SE: “Undocumented syntax of FilledCurve.”

Thanks John and Alexey! I can now (ab)use this feature :wink: