Message Boards Message Boards

GROUPS:

A problem of FindRoot with BSplineFunction

Posted 13 days ago
273 Views
|
9 Replies
|
3 Total Likes
|

Hi! I have a problem like the following,

data={{-1,2.9},{0.5,3.6},{1.0,5.5},{1.5,-4.2},{2.0,3.5}};
f=BSplineFunction[data];
FindRoot[f[t][[1]]==0,{t,0,0.2}]

However, FindRoot firstly wokes like f[t][[1]]=t, but not to find the root of the first argument of f[t]. How can I get the root which one I wanted? Thanks!

9 Replies

BSplineFunction returns a parameterized function with a domain that goes from 0 to 1. You need to find your root in the region between 0 and 1 and then use the function to get an {x,y} pair. Secondly, you can't use Part ([[]]) until the value is numeric because it will try to rip apart your spline function.

Show[Graphics[{Red, Point[data], Green, Line[data]}, Axes -> True], 
 ParametricPlot[f[t], {t, 0, 1}]]

will plot your spline with the control points and show you the parametric function:

enter image description here

To find a root when the y value of the parametric plot crosses zero, you need to force Part to wait until the value of the function is numeric.

g[t_?NumberQ] := Last[f[t]]

or

g[t_?NumberQ] := f[t][[2]]

g returns the y value of the parametric function, f.

you can test it

Plot[{t, g[t]}, {t, 0, 1}]

enter image description here

You plot from 0 to 1 and get the x values (a line) and the y values.

You can now get both roots:

In[24]:= r1 = FindRoot[g[t], {t, 0.4, 0.2, 1}]

Out[24]= {t -> 0.687292}

In[25]:= f[t] /. r1

Out[25]= {1.29408, 2.498*10^-16}

In[26]:= r2 = FindRoot[g[t], {t, 0.9, 0.2, 1}]

Out[26]= {t -> 0.885562}

In[27]:= f[t] /. r2

Out[27]= {1.69298, 1.55431*10^-15}

Regards,

Neil

Posted 13 days ago

Thank you very much, Neil Singer! The problem is that I don't know how to make FindRoot calculate f[t] at some point of division before giving the part of f[t]. Your direction is help me a lot.

Here is one more solution - for me it is the first time I can make use of FunctionInterpolation:

fi = FunctionInterpolation[First[f[t]], {t, 0, 1}];
FindRoot[fi[t], {t, .2}]
Posted 13 days ago

Thank you! It's a good idea to solve my problem.

I may have misunderstood which root you were trying to find. If you want to find the crossing of the x axis, as Henrik understood, then similarly you need to use First instead of Last in the g function above (or use Henrik's approach).

Regards.

Posted 13 days ago

It's not important. You two gave me some good ideas to deal with the problem. The key problem is how to find the root of any one component of BSplineFunction such as f[t] with FindRoot. f[t] is a two components function in some sense. Thank you again.

Best regards!

The key problem is how to find the root of any one component of BSplineFunction ...

Well, you could look for roots of the product of the components:

fi = FunctionInterpolation[Times @@ f[t], {t, 0, 1}]

(Somehow I could not avoid using FunctionInterpolation!) For finding (sort of) all roots in the interval [0, 1] you could try something (ugly) like this:

DeleteDuplicates[N@Round[\[FormalT] /. Quiet@FindRoot[fi[\[FormalT]], {\[FormalT], #}], 1*^-7] & /@ Range[0, 1, .2]]
(*  Out:   {0.1412204`,0.6872917`,0.8855624`}  *)

I have made my own implementation of BSplineFunction, to make it more usable:

BSplineCurveFunction[pts_?MatrixQ] := 
  Module[{knots, deg}, 
   knots = Rationalize@BSplineFunction[pts][[6, 1]]; 
   deg = BSplineFunction[pts][[3, 1]];
   Apply[Function, 
    List@
     Sum[
      pts[[i + 1]] BSplineBasis[{deg, knots}, i, #], {i, 0, 
       Length[pts] - 1}]]];
data = {{-1, 2.9}, {0.5, 3.6}, {1.0, 5.5}, {1.5, -4.2}, {2.0, 3.5}};
g[t_] = BSplineCurveFunction[data][t][[1]]
FindRoot[g[t] == 0, {t, 0, 0.2}]
Posted 10 days ago

Interesting implementation, thank you for sharing! Strongly related MMa.SE question with another implementation:

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract