2
$\begingroup$

I'm aiming to solve t for a 3D cubic Bézier curve define through 4 points (start pt, 1st handle, 2nd handle, end pt) at which the curve has a given tangent vector (or better, a parallel one:)

Background: I have a profile of an object (archaeological stuff), drawn through Bézier curves, and do have to operate some transformations on the segments, but wish to be able to preserve the extremities unchanged -> I do have to split/slice the curves, but wish to be able to specify the 'slope' at which the curves has to be sliced. Yes, the derivative of the Bézier function...

So far, I have no success for this case with the FindRoot, Solve etc., but I'm a newbie and... please be tolerant, first question ever asked :)

Here a exemple:

 bezierCurve = {{0., 0., 0.}, {1.62, 0., 0.}, {3.96, 0., -0.18}, {4.42, 0., -0.64}}

(Upper quarter of the front profile drawing of a French Neolithic copper axe blade, if you ask...)

f = BezierFunction[bezierCurve]
f'[1] 
(* {1.38, 0., -1.38} *)

which, for me, is equivalent to -Pi/4 or (-45°) on the x-z axes. So the tangent of this curve is running from {1, 0, 0} to {1/Sqrt[2], 0, -1/Sqrt[2]} Hence the question: how do I solve the t at which the derivative is parallel to a given vector?

THANKS A LOT

$\endgroup$
  • $\begingroup$ Hi welcome to Mathematica SE. One thing that is not too clear about your post is your definition of t? Is this meant to be a vector or a unit speed parametrization of your BezierCurve? $\endgroup$ – Dunlop Mar 21 '17 at 19:16
  • $\begingroup$ the speed parametrisation {t,0,1} $\endgroup$ – B-Lertch Mar 21 '17 at 19:28
  • $\begingroup$ @Dunlop, in fact, due to the complexity of the arclength expression for a general Bézier curve, it would be impractical here to have a unit-speed parametrization. $\endgroup$ – J. M. is away Mar 22 '17 at 3:36
2
$\begingroup$

If I understand your question correctly, you want to find t that makes f'[t] parallel to vec, where vec is specified in advance. We will find t that makes cross product of f' with the given vec zero.

bezierCurve = {{0., 0., 0.}, {1.62, 0., 0.}, {3.96, 0., -0.18}, {4.42, 0., -0.64}};
f = BezierFunction[bezierCurve];
vec = {1, 0, -0.4};
fr = FindRoot[Norm[Cross [f'[t], vec]], {t, 0.5, 0, 0.9999}];
u = t /. fr
(* 0.854603 *)
Show[ParametricPlot3D[f[t], {t, 0, 1}], 
 Graphics3D@{Red, PointSize -> 0.01, Point[f[u]], Green,Arrow[{f[u], f[u] + vec/2}]}, 
 PlotRange -> {{0, 5}, {-1, 1}, {-1, 0}}]

enter image description here

$\endgroup$
  • $\begingroup$ Perfect, exactly what I wanted:) The only thing which remain obscure to me is why it seems not practicable to specify the whole 'domain' (0 to 1) for the FindRood Min, Max search value. Anyway, thank you a lot for this clear and efficient answer! $\endgroup$ – B-Lertch Mar 22 '17 at 19:41
2
$\begingroup$

An alternative is to explicitly construct the representation of your Bézier curve in terms of the Bernstein basis, and then use NSolve[] to solve the resulting polynomial equation for the desired parameter value(s):

pts = {{0., 0., 0.}, {1.62, 0., 0.}, {3.96, 0., -0.18}, {4.42, 0., -0.64}};
d = Length[pts] - 1;
bfx[t_] = PiecewiseExpand[BernsteinBasis[d, Range[0, d], t].pts, 0 < t < 1];

NSolve[#.# &[Cross[bfx'[t], {1/Sqrt[2], 0, -1/Sqrt[2]}]] == 0 && 0 <= t <= 1, t, Reals]
   {{t -> 1.}, {t -> 1.}}

In this specific case, only one solution (with multiplicity 2) was returned, but this will return all possible solutions in general. Once you have the parameter value, you can proceed as in BlacKow's answer.

$\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.