# How to fix problems solving for values of BSpline function?

I generated a spline function called f using the BSplineFunction with domain {t,0,1}.

f = BSplineFunction[{{0., 5.81152}, {-0.909122, 5.73997}, {-1.86805, 5.5031},
{-1.79586, 5.52709}, {-2.40811, 5.28912}, {-3.4109, 4.70527}, {-4.68131,   3.501},
{-4.93131, 2.99958}, {-5.09697, 2.6673}, {-5.34697, 2.16588}, {-5.59697, 1.66446},
{-5.84697, 1.16304}}, SplineWeights -> {10, 10, 10, 1, 1, 1, 1, 1, 1, 10, 10, 10}]


I then wanted to find the point at which the function intersects the line from which points used to generate the spline were taken from. Graphically, I know the intersection occurs within the domain of f.

k[t_] = {-4.93131 - 0.915666 t, 2.99958 - 1.83654 t}


However, running the code:

FindRoot[First[k[0]] == First[f[t]], {t, .5, 0, 1}]


where k[0] is the end of the line produces a negative number. Is there a way to solve for the meeting points of those two functions?

-
I Believe that you should provide the functions. –  Öskå Jul 1 '14 at 13:48
There are the functions! @Öskå –  Kaisey Jul 1 '14 at 16:15
What's f? Did you mean g? Plus there are more problems (in addition to the extra square bracket in your FindRoot). For instance, First[g[t]] just yields t. So your FindRoot statements reduces to FindRoot[-4.93131==t,{t,0.5}] which will return t->-4.9313. –  rhomboidRhipper Jul 1 '14 at 16:34
@rhomboidRhipper The syntax problems should be fixed. f[t] does not return a value of t...it yields x and y coordinates for the domain 0<t<1. FindRoot[First[k[0]] == First[f[t]], {t, .5, 0, 1}] should yield the value of t at which the x coordinate is equal to -4.93131. Is that correct or am I completely missing something? –  Kaisey Jul 2 '14 at 13:34

Clear["Global*"]
pts = {{1, 1}, {2, 3}, {3, -1}, {4, 1}, {5, 0}};
f1 = Interpolation[pts, InterpolationOrder -> 1];
f2 = BSplineFunction[pts];
Show[Graphics[{Red, Point[pts], PointSize[0.02],
Point[f2 /@ {0.2, 0.4}], Green, Line[pts]}, Axes -> True],
ParametricPlot[f2[t], {t, 0, 1}]]


First,determine approximate range of t, in my example tmin=0.2,tmax=0.4.

Then,use method of dichotomy to find the point we need.

dichotomy[{t1_, t2_}] :=
Module[{x1, x2, y1, y2, tmid, x3, y3},
{x1, x2} = First@f2[#] & /@ {t1, t2};
{y1, y2} = f1 /@ {x1, x2};
tmid = (t1 + t2)/2;
{x3, y3} = f2[tmid];
If[(y1 - Last@f2@t1)*(f1[x3] - Last@f2@tmid) < 0, {t1, tmid}, {tmid, t2}]
]
tmin = 0.2; tmax = 0.4; error = 10^-5.;
ans = First@NestWhile[dichotomy, {0.2, 0.4},
With[{p = f2@First@#}, f1@First@p - Last@p > error] &]


0.306755

Last, check the ans

f2[ans]
f1@First@f2[ans]


{2.3914, 1.4344}

1.4344

-
Thank you! @Chenminqi Although, with the shorthand, I'm having trouble understanding the dichotomy function. Would you mind explaining? –  Kaisey Jul 1 '14 at 16:46

My approach, since BSplineFunction evaluates to a pair of numbers only when t is numeric, would be wrap the difference in a function protected by ?NumericQ:

rooteq[t_?NumericQ] := First[k[0]] - First[f[t]]

FindRoot[rooteq[t], {t, .5, 0, 1}]
(*
{t -> 0.674177}
*)

f[t] /. %
k[0]
(*
{-4.93131, 2.99958}
{-4.93131, 2.99958}
*)


The problem with the original code has been pointed out in a comment by @rhomboidRhipper. Just to illustrate that f[t] does not evaluate to a pair of numbers and that the equation that FindRoot deals with is -4.93131==t as @rhomboidRhipper claimed. The expression f[t] evaluates to BSplineFunction[{{0., 1.}}, <>][t], whose expression in position 1 is the argument t:

f[t]
First[f[t]]
(* BSplineFunction[{{0., 1.}}, <>][t] *)
(* t *)

First[k[0]] == First[f[t]]
(* -4.93131 == t *)

FindRoot[First[k[0]] == First[f[t]], {t, 0.5, -5, 1}]
(* {t -> -4.93131} *)


Note when the search region is extended to -5, FindRoot` locates the solution without complaint.

-