12
$\begingroup$

Bug introduced in version 10.0 and persisting through 11.0.1 or later
DiscretizeGraphics is new in 10.0.


I need to create a discretized region from a BezierCurve.

This is one of my curves:

pt = {{93.2759`, 277.0452`}, {90.6249`, 
      273.3252`}, {79.7499`, 255.70020000000002`}, {76.9999`, 
      250.70020000000002`}, {74.2499`, 
      245.70020000000002`}, {70.2499`, 
      237.70020000000002`}, {69.9999`, 235.32520000000002`}};
g = Graphics[{BezierCurve[pt]}];

DiscretizeGraphics creates points which are close to the curve, but clearly not on it.

Please try

Show[g, DiscretizeGraphics[g]]

This is a magnified portion of the result:

enter image description here

There is a small but consistent difference between the discretized version and the original graphics.

What is going on?

Which one is wrong? The BezierCurve rendering or the discretization? If it's the discretization, then:

What workarounds are there for the problem? Could I sample the points on the curve using BezierFunction? If yes, how exactly? BezierFunction[points] and BezierCurve[points] don't seem to represent the same curve.


My ultimate aim is to discretize some objects imported from a PDF. One of them is a closed JoinedCurve (or FilledCurve) and I need to use it to filter certain points which are inside the region. The other one (shown above) is a non-closed JoinedCurve, consisting of BezierCurve[..., SplineDegree -> 3] and Line[...] segments. DiscretizeGraphics does not work on JoinedCurve/FilledCurve.


Additional information:

BezierFunction and BezierCurve do not give the same result in the following test:

ParametricPlot[BezierFunction[pt][x], {x, 0, 1}, Epilog -> {BezierCurve[pt]}]

Again there is a small but consistent difference. Why?

Here's a different point set where BezierCurve and BezierFunction give very different results. How can I use BezierFunction to reproduce the same thing I see with BezierCurve?

pt = {{85.6699, 270.639}, {81.4849, 265.53}, {72.1939, 247.082}, {69.5059, 
  244.27}, {66.8189, 241.46}, {65.3979, 237.927}, {64.1759, 
  236.649}, {62.9539, 235.372}, {75.0969, 229.142}, {76.6069, 
  228.676}, {78.1179, 228.21}, {75.1319, 234.644}, {75.2469, 
  237.147}, {75.3609, 239.65}, {80.5859, 252.02}, {82.9949, 
  256.076}, {85.4049, 260.131}, {92.1679, 270.779}, {93.5919, 
  274.19}, {95.0159, 277.6}, {92.9719, 279.555}, {85.6699, 270.639}}

Posted a related question on Wolfram Community.

$\endgroup$
  • $\begingroup$ You can export a bspline as pdf then import the pdf. See my answer here. $\endgroup$ – Silvia Oct 29 '15 at 11:42
  • $\begingroup$ The other possibility is to use ParametricPlot[] + BezierFunction[] to create a Line[] primitive that should now be easily discretized. Can you give an example where BezierCurve[] doesn't seem to give the same result as my proposal? $\endgroup$ – J. M. is away Oct 29 '15 at 11:44
  • $\begingroup$ With respect to JoinedCurve[]/FilledCurve[]: if memory serves Simon Woods has a post somewhere on how to split those into components. $\endgroup$ – J. M. is away Oct 29 '15 at 11:45
  • $\begingroup$ @J.M. The same example from this post doesn't. ParametricPlot[BezierFunction[pt][x], {x, 0, 1}, Epilog -> {BezierCurve[pt]}], where pt are the points from above. $\endgroup$ – Szabolcs Oct 29 '15 at 11:46
  • $\begingroup$ @Silvia If I export/import to/from PDF, I still get a JoinedCurve with a BezierCurve inside (after decoding using GeometricFunctions`DecodeJoinedCurve), so I'm back to the same problem. There's also an additional problem: the coordinates have all changed. I need to do measurements on these objects (imported form a single PDF), so they must all be in the same coordinate system. $\endgroup$ – Szabolcs Oct 29 '15 at 11:50
11
$\begingroup$

This was solved with help from Shutao Tang, J.M., Sander Huisman and Eric Rimbey.

  1. Why do BezierFunction[pt] and BezierCurve[pt] not agree?

    Because BezierCurve uses SplineDegree -> 3 by default and BezierFunction always uses degree Length[pt] - 1 (not settable).

  2. Why does DiscretizeGraphics give a bad result?

    Because it appears to use (the equivalent of) BezierFunction[pt] internally. This is a bug. Witness:

    pt = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {2, 0}};
    g = Graphics[{BezierCurve[pt]}];
    Show[g, 
      ParametricPlot[BezierFunction[pt][x], {x, 0, 1}, 
       PlotStyle -> Directive[AbsoluteThickness[3], Yellow]], 
     DiscretizeGraphics[g]
    ]
    

    Mathematica graphics

  3. How can we reproduce a BezierCurve using BezierFunction?

    By stitching together several degree-3 (or less) BezierFunctions:

    funs = BezierFunction /@ Partition[pt, 4, 3, {1, 1}, {}];
    Show[Table[ParametricPlot[f[x], {x, 0, 1}], {f, funs}], PlotRange -> All]
    

    Mathematica graphics

    DiscretizeGraphics can then be applied to this.

$\endgroup$
  • $\begingroup$ do you get an error when you enter the line funs = BezierFunction /@ Partition[pt, 4, 3, {1, 1}, {}];? I find that the Partition command creates a list whose last element only has one point. I can only get it to work without error if I add [[;;-2]] after the Partition $\endgroup$ – Jason B. Dec 11 '15 at 11:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.