1function inurbs = nrbkntins(nurbs,iknots)
2%
3% NRBKNTINS: Insert a single or multiple knots into a NURBS curve,
4%            surface or volume.
5%
6% Calling Sequence:
7%
8%   icrv = nrbkntins(crv,iuknots);
9%   isrf = nrbkntins(srf,{iuknots ivknots});
10%   ivol = nrbkntins(vol,{iuknots ivknots iwknots});
11%
12% INPUT:
13%
14%   crv		: NURBS curve, see nrbmak.
15%
16%   srf		: NURBS surface, see nrbmak.
17%
18%   srf		: NURBS volume, see nrbmak.
19%
20%   iuknots	: Knots to be inserted along U direction.
21%
22%   ivknots	: Knots to be inserted along V direction.
23%
24%   iwknots	: Knots to be inserted along W direction.
25%
26% OUTPUT:
27%
28%   icrv	: new NURBS structure for a curve with knots inserted.
29%
30%   isrf	: new NURBS structure for a surface with knots inserted.
31%
32%   ivol	: new NURBS structure for a volume with knots inserted.
33%
34% Description:
35%
36%   Inserts knots into the NURBS data structure, these can be knots at
37%   new positions or at the location of existing knots to increase the
38%   multiplicity. The knot multiplicity can be increased up to the order of
39%   the spline. Any further increase of the multiplicity will generate zero
40%   basis functions, but not cause any error in the code.
41%   This function use the B-Spline function bspkntins, which interfaces to
42%   an internal 'C' routine.
43%
44% Examples:
45%
46%   Insert two knots into a curve, one at 0.3 and another
47%   twice at 0.4
48%
49%   icrv = nrbkntins(crv, [0.3 0.4 0.4])
50%
51%   Insert into a surface two knots as (1) into the U knot
52%   sequence and one knot into the V knot sequence at 0.5.
53%
54%   isrf = nrbkntins(srf, {[0.3 0.4 0.4] [0.5]})
55%
56% See also:
57%
58%   bspkntins
59%
60% Note:
61%
62%   The knot multiplicty can be increased beyond the order of the spline
63%   without causing errors, but the added basis functions will be equal to
64%   zero.
65%
66%    Copyright (C) 2000 Mark Spink, 2010 Rafael Vazquez
67%
68%    This program is free software: you can redistribute it and/or modify
69%    it under the terms of the GNU General Public License as published by
70%    the Free Software Foundation, either version 3 of the License, or
71%    (at your option) any later version.
72
73%    This program is distributed in the hope that it will be useful,
74%    but WITHOUT ANY WARRANTY; without even the implied warranty of
75%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
76%    GNU General Public License for more details.
77%
78%    You should have received a copy of the GNU General Public License
79%    along with this program.  If not, see <http://www.gnu.org/licenses/>.
80
81if nargin < 2
82  error('Input argument must include the NURBS and knots to be inserted');
83end
84
85if ~isstruct(nurbs)
86  error('NURBS representation is not structure!');
87end
88
89if ~strcmp(nurbs.form,'B-NURBS')
90  error('Not a recognised NURBS representation');
91end
92
93degree = nurbs.order-1;
94
95if iscell(nurbs.knots)
96 fmax = @(x,y) any (y > max(x)); fmin = @(x,y) any (y < min(x));
97 if (any(cellfun(fmax, nurbs.knots, iknots)) || any(cellfun(fmin, nurbs.knots, iknots)))
98   error ('Trying to insert a knot outside the interval of definition')
99 end
100
101 if size(nurbs.knots,2)==3
102  % NURBS represents a volume
103  num1 = nurbs.number(1);
104  num2 = nurbs.number(2);
105  num3 = nurbs.number(3);
106
107  % Insert knots along the w direction
108  if isempty(iknots{3})
109    coefs = nurbs.coefs;
110    knots{3} = nurbs.knots{3};
111  else
112    coefs = reshape(nurbs.coefs,4*num1*num2,num3);
113    [coefs,knots{3}] = bspkntins(degree(3),coefs,nurbs.knots{3},iknots{3});
114    num3 = size(coefs,2);
115    coefs = reshape(coefs,[4 num1 num2 num3]);
116  end
117
118  % Insert knots along the v direction
119  if isempty(iknots{2})
120    knots{2} = nurbs.knots{2};
121  else
122    coefs = permute(coefs,[1 2 4 3]);
123    coefs = reshape(coefs,4*num1*num3,num2);
124    [coefs,knots{2}] = bspkntins(degree(2),coefs,nurbs.knots{2},iknots{2});
125    num2 = size(coefs,2);
126    coefs = reshape(coefs,[4 num1 num3 num2]);
127    coefs = permute(coefs,[1 2 4 3]);
128  end
129
130  % Insert knots along the u direction
131  if isempty(iknots{1})
132    knots{1} = nurbs.knots{1};
133  else
134    coefs = permute(coefs,[1 3 4 2]);
135    coefs = reshape(coefs,4*num2*num3,num1);
136    [coefs,knots{1}] = bspkntins(degree(1),coefs,nurbs.knots{1},iknots{1});
137    coefs = reshape(coefs,[4 num2 num3 size(coefs,2)]);
138    coefs = permute(coefs,[1 4 2 3]);
139  end
140
141 elseif size(nurbs.knots,2)==2
142  % NURBS represents a surface
143  num1 = nurbs.number(1);
144  num2 = nurbs.number(2);
145
146  % Insert knots along the v direction
147  if isempty(iknots{2})
148    coefs = nurbs.coefs;
149    knots{2} = nurbs.knots{2};
150  else
151    coefs = reshape(nurbs.coefs,4*num1,num2);
152    [coefs,knots{2}] = bspkntins(degree(2),coefs,nurbs.knots{2},iknots{2});
153    num2 = size(coefs,2);
154    coefs = reshape(coefs,[4 num1 num2]);
155  end
156
157  % Insert knots along the u direction
158  if isempty(iknots{1})
159    knots{1} = nurbs.knots{1};
160  else
161    coefs = permute(coefs,[1 3 2]);
162    coefs = reshape(coefs,4*num2,num1);
163    [coefs,knots{1}] = bspkntins(degree(1),coefs,nurbs.knots{1},iknots{1});
164    coefs = reshape(coefs,[4 num2 size(coefs,2)]);
165    coefs = permute(coefs,[1 3 2]);
166  end
167 end
168else
169
170  if (any(iknots > max(nurbs.knots)) || any(iknots < min(nurbs.knots)))
171    error ('Trying to insert a knot outside the interval of definition')
172  end
173  % NURBS represents a curve
174  if isempty(iknots)
175    coefs = nurbs.coefs;
176    knots = nurbs.knots;
177  else
178    [coefs,knots] = bspkntins(degree,nurbs.coefs,nurbs.knots,iknots);
179  end
180
181end
182
183% construct new NURBS
184inurbs = nrbmak(coefs,knots);
185
186end
187
188%!demo
189%! crv = nrbtestcrv;
190%! plot(crv.coefs(1,:),crv.coefs(2,:),'bo')
191%! title('Knot insertion along test curve: curve and control polygons.');
192%! hold on;
193%! plot(crv.coefs(1,:),crv.coefs(2,:),'b--');
194%!
195%! nrbplot(crv,48);
196%!
197%! icrv = nrbkntins(crv,[0.125 0.375 0.625 0.875] );
198%! plot(icrv.coefs(1,:),icrv.coefs(2,:),'ro')
199%! plot(icrv.coefs(1,:),icrv.coefs(2,:),'r--');
200%! hold off