1 function nurbs = nrbmak(coefs,knots)
3 % NRBMAK: Construct the NURBS structure given the control points
8 % nurbs = nrbmak(cntrl,knots);
12 % cntrl : Control points, these can be either Cartesian or
13 % homogeneous coordinates.
15 % For a curve the control points are represented by a
16 % matrix of size (dim,nu), for a surface a multidimensional
17 % array of size (dim,nu,nv), for a volume a multidimensional array
18 % of size (dim,nu,nv,nw). Where nu is number of points along
19 % the parametric U direction, nv the number of points along
20 % the V direction and nw the number of points along the W direction.
21 % dim is the dimension. Valid options
23 % 2 .... (x,y) 2D Cartesian coordinates
24 % 3 .... (x,y,z) 3D Cartesian coordinates
25 % 4 .... (wx,wy,wz,w) 4D homogeneous coordinates
27 % knots : Non-decreasing knot sequence spanning the interval
28 % [0.0,1.0]. It's assumed that the geometric entities
29 % are clamped to the start and end control points by knot
30 % multiplicities equal to the spline order (open knot vector).
31 % For curve knots form a vector and for surfaces (volumes)
32 % the knots are stored by two (three) vectors for U and V (and W)
33 % in a cell structure {uknots vknots} ({uknots vknots wknots}).
37 % nurbs : Data structure for representing a NURBS entity
41 % Both curves and surfaces are represented by a structure that is
42 % compatible with the Spline Toolbox from Mathworks
44 % nurbs.form .... Type name 'B-NURBS'
45 % nurbs.dim .... Dimension of the control points
46 % nurbs.number .... Number of Control points
47 % nurbs.coefs .... Control Points
48 % nurbs.order .... Order of the spline
49 % nurbs.knots .... Knot sequence
51 % Note: the control points are always converted and stored within the
52 % NURBS structure as 4D homogeneous coordinates. A curve is always stored
53 % along the U direction, and the vknots element is an empty matrix. For
54 % a surface the spline order is a vector [du,dv] containing the order
55 % along the U and V directions respectively. For a volume the order is
56 % a vector [du dv dw]. Recall that order = degree + 1.
60 % This function is used as a convenient means of constructing the NURBS
61 % data structure. Many of the other functions in the toolbox rely on the
62 % NURBS structure been correctly defined as shown above. The nrbmak not
63 % only constructs the proper structure, but also checks for consistency.
64 % The user is still free to build his own structure, in fact a few
65 % functions in the toolbox do this for convenience.
69 % Construct a 2D line from (0.0,0.0) to (1.5,3.0).
70 % For a straight line a spline of order 2 is required.
71 % Note that the knot sequence has a multiplicity of 2 at the
72 % start (0.0,0.0) and end (1.0 1.0) in order to clamp the ends.
74 % line = nrbmak([0.0 1.5; 0.0 3.0],[0.0 0.0 1.0 1.0]);
77 % Construct a surface in the x-y plane i.e
79 % ^ (0.0,1.0) ------------ (1.0,1.0)
85 % | (0.0,0.0) ------------ (1.0,0.0)
87 % |------------------------------------>
90 % coefs = cat(3,[0 0; 0 1],[1 1; 0 1]);
91 % knots = {[0 0 1 1] [0 0 1 1]}
92 % plane = nrbmak(coefs,knots);
93 % nrbplot(plane, [2 2]);
95 % Copyright (C) 2000 Mark Spink, 2010 Rafael Vazquez
97 % This program is free software: you can redistribute it and/or modify
98 % it under the terms of the GNU General Public License as published by
99 % the Free Software Foundation, either version 2 of the License, or
100 % (at your option) any later version.
102 % This program is distributed in the hope that it will be useful,
103 % but WITHOUT ANY WARRANTY; without even the implied warranty of
104 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105 % GNU General Public License for more details.
107 % You should have received a copy of the GNU General Public License
108 % along with this program. If not, see <http://www.gnu.org/licenses/>.
110 nurbs.form = 'B-NURBS';
115 if size(knots,2) == 3
118 elseif (numel(np)==2)
121 % constructing a volume
122 nurbs.number = np(2:4);
124 nurbs.coefs = repmat([0.0 0.0 0.0 1.0]',[1 np(2:4)]);
125 nurbs.coefs(1:dim,:,:) = coefs;
129 uorder = size(knots{1},2)-np(2);
130 vorder = size(knots{2},2)-np(3);
131 worder = size(knots{3},2)-np(4);
132 uknots = sort(knots{1});
133 vknots = sort(knots{2});
134 wknots = sort(knots{3});
135 uknots = (uknots-uknots(1))/(uknots(end)-uknots(1));
136 vknots = (vknots-vknots(1))/(vknots(end)-vknots(1));
137 wknots = (wknots-wknots(1))/(wknots(end)-wknots(1));
138 nurbs.knots = {uknots vknots wknots};
139 nurbs.order = [uorder vorder worder];
141 elseif size(knots,2) == 2
142 if (numel(np)==2); np(3) = 1; end
143 % constructing a surface
144 nurbs.number = np(2:3);
146 nurbs.coefs = repmat([0.0 0.0 0.0 1.0]',[1 np(2:3)]);
147 nurbs.coefs(1:dim,:,:) = coefs;
151 uorder = size(knots{1},2)-np(2);
152 vorder = size(knots{2},2)-np(3);
153 uknots = sort(knots{1});
154 vknots = sort(knots{2});
155 uknots = (uknots-uknots(1))/(uknots(end)-uknots(1));
156 vknots = (vknots-vknots(1))/(vknots(end)-vknots(1));
157 nurbs.knots = {uknots vknots};
158 nurbs.order = [uorder vorder];
164 % constructing a curve
165 nurbs.number = np(2);
167 nurbs.coefs = repmat([0.0 0.0 0.0 1.0]',[1 np(2)]);
168 nurbs.coefs(1:dim,:) = coefs;
172 nurbs.order = size(knots,2)-np(2);
174 nurbs.knots = (knots-knots(1))/(knots(end)-knots(1));
181 %! pnts = [0.5 1.5 4.5 3.0 7.5 6.0 8.5;
182 %! 3.0 5.5 5.5 1.5 1.5 4.0 4.5;
183 %! 0.0 0.0 0.0 0.0 0.0 0.0 0.0];
184 %! crv = nrbmak(pnts,[0 0 0 1/4 1/2 3/4 3/4 1 1 1]);
186 %! title('Test curve')
190 %! pnts = [0.5 1.5 4.5 3.0 7.5 6.0 8.5;
191 %! 3.0 5.5 5.5 1.5 1.5 4.0 4.5;
192 %! 0.0 0.0 0.0 0.0 0.0 0.0 0.0];
193 %! crv = nrbmak(pnts,[0 0 0 0.1 1/2 3/4 3/4 1 1 1]);
195 %! title('Test curve with a slight variation of the knot vector')
199 %! pnts = zeros(3,5,5);
200 %! pnts(:,:,1) = [ 0.0 3.0 5.0 8.0 10.0;
201 %! 0.0 0.0 0.0 0.0 0.0;
202 %! 2.0 2.0 7.0 7.0 8.0];
203 %! pnts(:,:,2) = [ 0.0 3.0 5.0 8.0 10.0;
204 %! 3.0 3.0 3.0 3.0 3.0;
205 %! 0.0 0.0 5.0 5.0 7.0];
206 %! pnts(:,:,3) = [ 0.0 3.0 5.0 8.0 10.0;
207 %! 5.0 5.0 5.0 5.0 5.0;
208 %! 0.0 0.0 5.0 5.0 7.0];
209 %! pnts(:,:,4) = [ 0.0 3.0 5.0 8.0 10.0;
210 %! 8.0 8.0 8.0 8.0 8.0;
211 %! 5.0 5.0 8.0 8.0 10.0];
212 %! pnts(:,:,5) = [ 0.0 3.0 5.0 8.0 10.0;
213 %! 10.0 10.0 10.0 10.0 10.0;
214 %! 5.0 5.0 8.0 8.0 10.0];
216 %! knots{1} = [0 0 0 1/3 2/3 1 1 1];
217 %! knots{2} = [0 0 0 1/3 2/3 1 1 1];
219 %! srf = nrbmak(pnts,knots);
220 %! nrbplot(srf,[20 20])
221 %! title('Test surface')
225 %! coefs =[ 6.0 0.0 6.0 1;
238 %! knots = [0 0 0 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1 1 1 1];
240 %! crv = nrbmak(coefs,knots);
243 %! title('3D helical curve.');