1

I have the following identity mapping expressed by tensor-product B-spline basis functions:

pts = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {0, 0}, {1, 0}, {-1,1}, {0, 1}, {1, 1}};
k = {-1, -1, 0, 1, 1};
nBasis = Sqrt[Length[pts]];
basisU = Table[BSplineBasis[{1, k}, i, u], {i, 0, nBasis - 1}];
basisV = Table[BSplineBasis[{1, k}, i, v], {i, 0, nBasis - 1}];
tensorProductBasis = Table[basisU[[i]] basisV[[j]], {j, 1, nBasis}, {i, 1, nBasis}];
tensorProductBasis = ArrayReshape[%, {1, nBasis^2}][[1]];
map = Sum[pts[[i]] tensorProductBasis[[i]], {i, 1, nBasis^2}];

I have also NURBS representation of a circle:

pts = {{.5, 0}, {1, 0}, {1, 1}, {.5, 1}, {0, 1}, {0, 0}, {.5, 0}};
w = {1, .5, .5, 1, .5, .5, 1};
k = {0, 0, 0, 1/4, 1/2, 1/2, 3/4, 1, 1, 1};
circle = BSplineFunction[pts, SplineWeights -> w, SplineKnots -> k];

I need to substitute the identity map variables $u$ and $v$ by the first and second components of B-spline function representing a circle and get expression depending on one variable only. When I am trying to do like this:

newMap = map /. {u -> circle[t][[1]], v -> circle[t][[2]]};

I get an error:

Part::partw: "Part 2 of BSplineFunction[{{0.,1.}},<>][t] does not exist

I would appreciate any advises.

S. S.
  • 13
  • 3

3 Answers3

1

Let me first try to rephrase the question to be sure we understand each other correctly.

You have a curve in the plane (circle in this case; cf. Fig. 1).

Before applying <code>map</code>.

You deform a portion of the plane enclosing the curve (i.e., circle) with map and you would like to see what the curve looks like afterwards. (I took a map different from identity to demonstrate the difference in Fig. 2.)

After applying <code>map</code>.

Now to the answer. The first possibility (trying to minimize changes in the code) is just to change the definition of newMap as follows.

newMap[t_] := Module[{}, u = circle[t][[1]]; v = circle[t][[2]]; map]

This way we locally change the values of u and v to be what we need them to.

However, I am not very happy with this solution -- your map is a hard-wired to be a function of variables u and v. If you change u or v elsewhere in your notebook, you can destroy your result (as an example, set u to .7 and observe the whole thing crumble).

What I would propose instead is to rework your code to use built-in function BSplineFunction.

pts = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {0, 0}, {1, 0}, {-1,1}, {0, 1}, {1, 1}};
k = {-1, -1, 0, 1, 1};
nBasis = Sqrt[Length[pts]];
(* We need a two-dimensional array of control points: *)
CPs = Table[pts[[(i - 1)*nBasis + j]], {i, 1, nBasis}, {j, 1, nBasis}];
map = BSplineFunction[CPs, SplineDegree -> 1, SplineKnots -> k]

Now keeping your definition of circle, all you need to add is the definition of newMap.

newMap[t_]:=map[circle[t][[1]],circle[t][[2]]]

Of course, whether this is a good solution depends on what you are going to do with it later on. Good luck!

Dominik Mokriš
  • 242
  • 1
  • 7
1

The solution is that you should have also used the NURBS representation for constructing the circle as well, since you already did it for the map. Let me first show a better way to build your mapping:

pts = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {0, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}};
k = {-1, -1, 0, 1, 1};
nBasis = Sqrt[Length[pts]];
basisU = Table[BSplineBasis[{1, k}, i, u], {i, 0, nBasis - 1}];
basisV = Table[BSplineBasis[{1, k}, i, v], {i, 0, nBasis - 1}];
map[u_, v_] = Flatten[Outer[Times, basisV, basisU]].pts;

Do something similar for the circle:

cpts = {{1/2, 0}, {1, 0}, {1, 1}, {1/2, 1}, {0, 1}, {0, 0}, {1/2, 0}};
cw = {1, 1/2, 1/2, 1, 1/2, 1/2, 1};
ck = {0, 0, 0, 1/4, 1/2, 1/2, 3/4, 1, 1, 1};
basisT = Table[BSplineBasis[{2, ck}, i - 1, t], {i, Length[cpts]}];
circ[t_] = (cw basisT).cpts/(cw.basisT);

Then, evaluate

ParametricPlot[map @@ circ[t], {t, 0, 1}]

and you should get the same figure as the one in grbl's answer. The differentiation you mentioned in a comment is expediently done as well:

ParametricPlot[D[map @@ circ[t], t] // Evaluate, {t, 0, 1}]

kidney

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
0

I have no idea what you are doing. The BSplineFunction needs to be evaluated a point. You could try

ClearAll[newMap]
newMap[t_] := map /. {u -> (circle[t] )[[1]], v -> (circle[t] )[[2]]};
ParametricPlot[newMap[t], {t, 0, 1}]

enter image description here

grbl
  • 1,042
  • 5
  • 14
  • Then I need to separate $x$- and $y$-components of the newMap, differentiate them w.r.t. $t$ and calculate the values of derivatives at a particular point. When I define functions derX[t_] := (newMap'[t])[[1]] and derY[t_] := (newMap'[t])[[2]] and try to calculate their values at a particular parameter value (e.g. derX[0.5] and derY[0.5]), I get unreasonable results. – S. S. Dec 03 '16 at 19:30