6
$\begingroup$

I have:

points = {{0, 100}, {250, 0}, {0, 300}, {500, 500}}

And I want to know the area below the curve, so I came to:

f = BezierFunction[points]

NIntegrate[f, {x, 0, 1}]

But it failed to execute:

NIntegrate::inumr: The integrand BezierFunction[{{0.,1.}},<>] has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1}}. >>

So how do I numerically integrate a Bézier curve correctly?

$\endgroup$
8
$\begingroup$

Since f[t] yields in effect {x[t], y[t]} and the area under a curve (with y[t] > 0) is given by the integral of y[t] x'[t] (i.e., $\int y\;dx$), then the following should work, assuming x[t] is increasing.

dA[f_, t_?NumericQ] := Last[f[t]] First[f'[t]];
NIntegrate[dA[f, t], {t, 0, 1}]
(*  150000.  *)

One can extend this to other forms, e.g. to closed curves, via Green's Theorem, with dA[f_, x_?NumericQ] := f[x].Cross[f'[x]]/2.

$\endgroup$
5
$\begingroup$

You should note that NIntegrate normally consumes standard functions or InterpolatingFunction. A BezierFunction is a parametric function and will not work right away with the integrator.

You can do the following by the way.

mesh = DiscretizeGraphics[ParametricPlot[f[t], {t, 0, 1}]];
nf = Interpolation[MeshCoordinates[mesh]];
NIntegrate[nf[x], Evaluate@Flatten@{x, nf["Domain"]}]

150000.

I basically took the point-wise representation of your BezierFunction from a parametric plot using the DiscretizeGraphics functionality of MMA. You can see the sampled points along with your curve.

enter image description here

Show[Graphics[{Red, PointSize[Large], Point[points], Orange, Dashed, 
   Line[points]}, Axes -> True], 
 ParametricPlot[f[t], {t, 0, 1}, 
  PlotStyle -> {{LightBlue, Thickness@.01}}], mesh, Frame -> True]

P.S: Note that the above process will not work on arbitrary BezierFunction as 2D Bézier curves are by definition allowed to resolve into an one to many mapping which can't be integrated.

$\endgroup$
4
$\begingroup$

The nice thing about Mathematica is that it often allows you to do a thing in more than one fashion. For this answer, I will evaluate the exact integral, using a slight tweak of Michael's strategy.

The wrinkle here is that we fall back on the definition of the Bézier curve as an appropriate linear combination of Bernstein functions. This allows you to have the $x$ and $y$ components of the curve kept separately.

Thus,

pts = {{0, 100}, {250, 0}, {0, 300}, {500, 500}};
n = Length[pts] - 1;
{f[t_], g[t_]} = BernsteinBasis[n, Range[0, n], t].pts;
Integrate[g[t] f'[t], {t, 0, 1}]
   150000
$\endgroup$

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.