]> Creatis software - CreaPhase.git/blob - octave_packages/nurbs-1.3.6/kntrefine.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / nurbs-1.3.6 / kntrefine.m
1 % KNTREFINE: Refine a given knot vector by dividing each interval uniformly,
2 %             maintaining the continuity in previously existing knots.
3 %
4 %   [rknots]                  = kntrefine (knots, n_sub, degree, regularity)
5 %   [rknots, zeta]            = kntrefine (knots, n_sub, degree, regularity)
6 %   [rknots, zeta, new_knots] = kntrefine (knots, n_sub, degree, regularity)
7 %
8 % INPUT:
9 %
10 %     knots:      initial knot vector.
11 %     n_sub:      number of new knots to be added in each interval.
12 %     degree:     polynomial degree of the refined knot vector
13 %     regularity: maximum global regularity 
14 %
15 % OUTPUT:
16 %
17 %     rknots:    refined knot vector
18 %     zeta:      refined knot vector without repetitions
19 %     new_knots: new knots, to apply the knot insertion
20 %
21 % The regularity at the new inserted knots is the one given by the user.
22 % At previously existing knots, the regularity is the minimum
23 %  between the previous regularity, and the one given by the user.
24 %  This ensures optimal convergence rates in the context of IGA.
25 %
26 % Copyright (C) 2010 Carlo de Falco, Rafael Vazquez
27 %
28 %    This program is free software: you can redistribute it and/or modify
29 %    it under the terms of the GNU General Public License as published by
30 %    the Free Software Foundation, either version 2 of the License, or
31 %    (at your option) any later version.
32
33 %    This program is distributed in the hope that it will be useful,
34 %    but WITHOUT ANY WARRANTY; without even the implied warranty of
35 %    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36 %    GNU General Public License for more details.
37 %
38 %    You should have received a copy of the GNU General Public License
39 %    along with this program.  If not, see <http://www.gnu.org/licenses/>.
40
41 function varargout = kntrefine (knots, n_sub, degree, regularity)
42
43   if (iscell(knots))
44     if (numel(n_sub)~=numel(degree) || numel(n_sub)~=numel(regularity) || ...
45         numel(n_sub)~=numel(knots))
46       error('kntrefine: n_sub, degree and regularity must have the same length as the number of knot vectors')
47     end
48     aux_knots = knots;
49   else
50     if (numel(n_sub)~=numel(degree) || numel(n_sub)~=numel(regularity) || ...
51         numel(n_sub)~=1)
52       error('kntrefine: n_sub, degree and regularity must have the same length as the number of knot vectors')
53     end
54     aux_knots = {knots};
55   end
56
57   if (nargout == 3)
58     for idim = 1:numel(n_sub)
59       if (degree(idim)+1 ~= sum (aux_knots{idim}==aux_knots{idim}(1)))
60         error ('kntrefine: new_knots is only computed when the degree is maintained');
61       end
62     end
63     for idim = 1:numel(n_sub)
64       min_mult     = degree(idim) - regularity(idim);
65       z            = unique (aux_knots{idim});
66       nz           = numel (z);
67       deg          = sum (aux_knots{idim} == z(1)) - 1;
68       rknots{idim} = z(ones(1, degree(idim)+1));
69       new_knots{idim} = [];
70  
71       for ik = 2:nz
72         insk = linspace (z(ik-1), z(ik), n_sub(idim) + 2);
73         insk = vec (repmat (insk(2:end-1), min_mult, 1))';
74         old_mult = sum (aux_knots{idim} == z(ik));
75         mult = max (min_mult, degree(idim) - deg + old_mult);
76         rknots{idim} = [rknots{idim}, insk, z(ik*ones(1, mult))];
77         new_knots{idim} = [new_knots{idim}, insk, z(ik*ones(1, mult-old_mult))];
78       end
79       zeta{idim} = unique (rknots{idim});
80     end
81     if (~iscell(knots))
82       rknots = rknots{1};
83       zeta = zeta{1};
84       new_knots = new_knots{1};
85     end
86     varargout{1} = rknots;
87     varargout{2} = zeta;
88     varargout{3} = new_knots;
89   else
90     for idim = 1:numel(n_sub)
91       min_mult     = degree(idim) - regularity(idim);
92       z            = unique (aux_knots{idim});
93       nz           = numel (z);
94       deg          = sum (aux_knots{idim} == z(1)) - 1;
95       rknots{idim} = z(ones(1, degree(idim)+1));
96  
97       for ik = 2:nz
98         insk = linspace (z(ik-1), z(ik), n_sub(idim) + 2);
99         insk = vec (repmat (insk(2:end-1), min_mult, 1))';
100         old_mult = sum (aux_knots{idim} == z(ik));
101         mult = max (min_mult, degree(idim) - deg + old_mult);
102         rknots{idim} = [rknots{idim}, insk, z(ik*ones(1, mult))];
103       end
104       zeta{idim} = unique (rknots{idim});
105     end
106     if (~iscell(knots))
107       rknots = rknots{1};
108       zeta = zeta{1};
109     end
110     varargout{1} = rknots;
111     if (nargout == 2)
112       varargout{2} = zeta;
113     end
114   end
115 end
116
117 function v = vec (in)
118   v = in(:);
119 end
120
121 %!shared nrbs
122 %!test
123 %! knots = {[0 0 1 1] [0 0 0 1 1 1]};
124 %! coefs(1,:,:) = [1 sqrt(2)/2 0; 2 sqrt(2) 0];
125 %! coefs(2,:,:) = [0 sqrt(2)/2 1; 0 sqrt(2) 2];
126 %! coefs(4,:,:) = [1 sqrt(2)/2 1; 1 sqrt(2)/2 1];
127 %! nrbs = nrbmak (coefs, knots);
128 %! nrbs = nrbkntins (nrbs, {[] [0.5 0.6 0.6]});
129 %! nrbs = nrbdegelev (nrbs, [0 1]);
130 %! nrbs = nrbkntins (nrbs, {[] [0.4]});
131 %! rknots = kntrefine (nrbs.knots, [1 1], [1 1], [0 0]);
132 %! assert (rknots{1} == [0 0 0.5 1 1]);
133 %! assert (rknots{2} == [0 0 0.2 0.4 0.45 0.5 0.55 0.6 0.8 1 1]);
134 %!
135 %!test
136 %! rknots = kntrefine (nrbs.knots, [1 1], [3 3], [0 0]);
137 %! assert (rknots{1}, [0 0 0 0 0.5 0.5 0.5 1 1 1 1]);
138 %! assert (rknots{2}, [0 0 0 0 0.2 0.2 0.2 0.4 0.4 0.4 0.45 0.45 0.45 0.5 0.5 0.5 0.55 0.55 0.55 0.6 0.6 0.6 0.8 0.8 0.8 1 1 1 1]);
139 %!
140 %!test
141 %! rknots = kntrefine (nrbs.knots, [1 1], [3 3], [2 2]);
142 %! assert (rknots{1}, [0 0 0 0 0.5 1 1 1 1]);
143 %! assert (rknots{2}, [0 0 0 0 0.2 0.4 0.45 0.5 0.5 0.55 0.6 0.6 0.6 0.8 1 1 1 1]);
144 %!
145 %!test
146 %! rknots = kntrefine (nrbs.knots, [1 1], [4 4], [0 0]);
147 %! assert (rknots{1}, [0 0 0 0 0 0.5 0.5 0.5 0.5 1 1 1 1 1]);
148 %! assert (rknots{2}, [0 0 0 0 0 0.2 0.2 0.2 0.2 0.4 0.4 0.4 0.4 0.45 0.45 0.45 0.45 0.5 0.5 0.5 0.5 0.55 0.55 0.55 0.55 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.8 1 1 1 1 1]);
149 %!
150 %!test
151 %! rknots = kntrefine (nrbs.knots, [1 1], [4 4], [3 3]);
152 %! assert (rknots{1}, [0 0 0 0 0 0.5 1 1 1 1 1]);
153 %! assert (rknots{2}, [0 0 0 0 0 0.2 0.4 0.4 0.45 0.5 0.5 0.5 0.55 0.6 0.6 0.6 0.6 0.8 1 1 1 1 1]);
154 %!
155 %!test
156 %! knots = [0 0 0 0 0.4 0.5 0.5 0.6 0.6 0.6 1 1 1 1];
157 %! rknots = kntrefine (knots, 1, 4, 3);
158 %! assert (rknots, [0 0 0 0 0 0.2 0.4 0.4 0.45 0.5 0.5 0.5 0.55 0.6 0.6 0.6 0.6 0.8 1 1 1 1 1]);