comparison extra/nurbs/inst/basiskntins.m @ 12641:e3998369a32e octave-forge

Added function to compute subdivision coefficients
author rafavzqz
date Fri, 19 Jun 2015 16:24:09 +0000
parents
children 7623d14dd29c
comparison
equal deleted inserted replaced
12640:de98e4cb9248 12641:e3998369a32e
1 function S = basiskntins (deg,t,u)
2
3 % Compute the coefficient matrix for non-uniform B-splines subdivision.
4 %
5 % This represents the B-spline basis given by a coarse knot vector
6 % in terms of the B-spline basis of a finer knot vector.
7 %
8 % The function is implemented for the univariate case. It is based on
9 % the paper:
10 %
11 % G. Casciola, L. Romani, A general matrix representation for non-uniform
12 % B-spline subdivision with boundary control, ALMA-DL, University of Bologna (2007)
13 %
14 % Calling Sequence:
15 %
16 % S = basisfun_kntins (deg, t, u);
17 %
18 % INPUT:
19 %
20 % deg - degree of the first knot vector
21 % t - coarse knot vector
22 % u - fine knot vector
23 %
24 % OUTPUT:
25 %
26 % B - Value of the basis functions at the points
27 % size(B)=[numel(u),(p+1)] for curves
28 % or [numel(u)*numel(v), (p+1)*(q+1)] for surfaces
29 %
30 % N - Indices of the basis functions that are nonvanishing at each
31 % point. size(N) == size(B)
32 %
33 % Copyright (C) 2015 Rafael Vazquez
34 %
35 % This program is free software: you can redistribute it and/or modify
36 % it under the terms of the GNU General Public License as published by
37 % the Free Software Foundation, either version 3 of the License, or
38 % (at your option) any later version.
39
40 % This program is distributed in the hope that it will be useful,
41 % but WITHOUT ANY WARRANTY; without even the implied warranty of
42 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 % GNU General Public License for more details.
44 %
45 % You should have received a copy of the GNU General Public License
46 % along with this program. If not, see <http://www.gnu.org/licenses/>.
47
48 nt = length(t);
49 nu = length(u);
50 S = sparse (nu-deg-1,nt-deg-1);
51 [t_mult,t_single,nt_s] = knot_mult(deg,t);
52 [u_mult,u_single,nu_s] = knot_mult(deg,u);
53 st = deg+1;
54 su = deg+1;
55 row = 1;
56 col = 1;
57 Sl = bs2bs(deg,t,u,st,su);
58 S(row:deg+row,col:deg+col) = Sl;
59 t_single(nt+1) = t(nt-deg);
60 i = 1;
61
62 for j=1:nu_s
63 if (u_single(j) == t_single(i))
64 st = st+t_mult(i);
65 col = col+t_mult(i);
66 i = i+1;
67 end
68 su = su+u_mult(j);
69 row = row+u_mult(j);
70 Sl = bs2bs(deg,t,u,st,su);
71 S(row:deg+row,col:deg+col) = Sl;
72 end
73
74 end
75
76
77 function [t_mult,t_single,nt_s] = knot_mult(d,t)
78 epsilon = 1e-14 * (t(end) - t(1));
79
80 nt = length(t);
81 nt_s = 0;
82 m = 1;
83 for i = d+2:nt-d-1
84 if ((t(i+1) - t(i)) > epsilon)
85 nt_s = nt_s+1;
86 t_mult(nt_s) = m;
87 t_single(nt_s) = t(i);
88 m=1;
89 else
90 m = m+1;
91 end
92 end
93 t_single(nt_s+1)=t(nt-d);
94 t_mult(nt_s+1)=0;
95
96 end
97
98 function S = bs2bs(d,t,u,k,l)
99
100 S = zeros(d+1);
101 S(1,:) = bs2bs_first_row(d,t,u,k,l);
102
103 for ir=1:d
104 S(ir+1,:) = bs2bs_i_row(d,t,u,k,l,ir,S(ir,:));
105 end
106 end
107
108 function S = bs2bs_first_row(d,t,u,k,l)
109
110 S = eye(1,d+1);
111 for h=1:d
112 beta_2=0.0;
113 uu=u(l+1-h);
114 for j=h:-1:1
115 d1=uu-t(k+j-h);
116 d2=t(k+j)-uu;
117 beta_1=S(j)/(d2+d1);
118 S(j+1)=d1*beta_1+beta_2;
119 beta_2=d2*beta_1;
120 end
121 S(1)=beta_2;
122 end
123 end
124
125 function Si = bs2bs_i_row(d,t,u,k,l,ir,S)
126
127 Si(1) = S(1)*(t(k+1)-u(l+ir))/(t(k+1)-u(l+ir-d));
128
129 for j=1:d
130 den=t(k+j+1)-u(l+ir-d);
131 fact=(t(k+j+1)-t(k+j-d))/(t(k+j)-t(k+j-d-1));
132 Si(j+1)=(fact*(S(j)*(u(l+ir)-t(k+j-d-1))-Si(j) * ...
133 (u(l+ir-d)-t(k+j-d-1)))+S(j+1)*(t(k+j+1)-u(l+ir)))/den;
134 end
135 end
136
137 %!test
138 %! knt1 = [0 0 0 1/2 1 1 1];
139 %! knt2 = [0 0 0 1/4 1/2 3/4 1 1 1];
140 %! C = basiskntins (2, knt1, knt2);
141 %! assert (full(C), [1 0 0 0; 1/2 1/2 0 0; 0 3/4 1/4 0; 0 1/4 3/4 0; 0 0 1/2 1/2; 0 0 0 1]);
142
143 %!test
144 %! crv = nrbtestcrv;
145 %! crv2 = nrbkntins (crv, [0.1, 0.3, 0.4, 0.5, 0.6, 0.8, 0.96 0.98]);
146 %! C = basiskntins (crv.order-1,crv.knots,crv2.knots);
147 %! for ii = 1:4
148 %! assert (max (abs(C*crv.coefs(ii,:)' - crv2.coefs(ii,:)')) < 1e-14 )
149 %! end
150
151 %!test
152 %! crv = nrbtestcrv;
153 %! crv2 = nrbkntins (crv, [0.50000001, 0.5000001, 0.500001, 0.50001, 0.5001]);
154 %! C = basiskntins (crv.order-1,crv.knots,crv2.knots);
155 %! for ii = 1:4
156 %! assert (max (abs(C*crv.coefs(ii,:)' - crv2.coefs(ii,:)')) < 1e-14 )
157 %! end
158
159 %!test
160 %! crv = nrbtestcrv;
161 %! crv2 = nrbkntins (crv, [0.1, 0.3, 0.4, 0.5, 0.6, 0.8, 0.96 0.98]);
162 %! C = basiskntins (crv.order-1,crv.knots,crv2.knots);
163 %! x = linspace (0, 1, 10);
164 %! s = findspan (crv.number-1, crv.order-1, x, crv.knots);
165 %! s2 = findspan (crv2.number-1, crv2.order-1, x, crv2.knots);
166 %! N = basisfun (s, x, crv.order-1, crv.knots);
167 %! N2 = basisfun (s2, x, crv2.order-1, crv2.knots);
168 %! c = numbasisfun (s, x, crv.order-1, crv.knots) + 1;
169 %! c2 = numbasisfun (s2, x, crv2.order-1, crv2.knots) + 1;
170 %! for ii = 1:numel(x)
171 %! assert (abs(N2(ii,:) * C(c2(ii,:),c(ii,:)) - N(ii,:)) < 1e-14)
172 %! end