├── Basis.m ├── BasisTest.m └── Project ├── Contents.m ├── NURBS Paper.pdf ├── PSOhelper ├── NURBS │ ├── basisgen.m │ ├── ikgen.m │ ├── knotgen.m │ └── surfacegen.m └── Parameterization │ └── indexer.m ├── PSnurbs.m ├── Reference Paper.pdf ├── displayPSO.m ├── objective.m └── test ├── Nurbstester.m ├── objtester.m ├── spheredemo.m └── surfacedemo.m /Basis.m: -------------------------------------------------------------------------------- 1 | % Basis.m 2 | % Description: Generates the basis functions used for Nurbs curve 3 | % construction. 4 | % Inputs: 5 | % ppoint (u,v) - paramaterized surface variable. 6 | % knot (S,T) - knot vector 7 | % order (k,l) - order of spline curve* 8 | % maxindex (m,n) - maximum index in meshgrid 9 | % Outputs: 10 | % N - Matrix with all spline values calculated 11 | % *Note: Order refers to 0...(k/l) wheras degree refers to 1...(k/l)-1. 12 | function N = Basis(ppoint,knot,order,maxindex) 13 | % Initailize empty matrix: 14 | % Fill matrix with all first order splines: 15 | for i=1:numel(knot)-1 16 | if (knot(i)<=ppoint) && (ppoint>>>>>> origin/master 35 | if temp1 == 0 && temp2 == 0; 36 | temp3 = 0; 37 | else 38 | temp3 = temp1 / temp2 39 | end 40 | temp4 = ( knot(i+k) - ppoint ) * N(i+1,k-1) 41 | temp5 = ( knot(i+k)- knot(i+1) ) 42 | if temp4 == 0 && temp5 == 0 43 | temp6 = 0; 44 | else 45 | temp6 = temp4 / temp5 46 | end 47 | N(i,k) = double(temp3) + double(temp6); 48 | end 49 | end 50 | N_order = N(:,order); -------------------------------------------------------------------------------- /BasisTest.m: -------------------------------------------------------------------------------- 1 | clc;clear all;close all; 2 | % BasisTest.m 3 | % Description: Testscript for Basis function. 4 | % 1-D Test: B-spline curve 5 | %% Initialize Test Variables: 6 | ppoint = 0:0.2:1; % Contains 6 values. 7 | ptsx = [0 2 4 5]; 8 | ptsy = [1 4 5 3]; 9 | pts = [ptsx' ptsy']; % 4 points total 10 | order = 2; 11 | maxindex = numel(ptsx); 12 | r = order + numel(ptsx); 13 | flag = 0; 14 | knot = [0 0 0 0.4 1 1 1]; % 7 knot values. 15 | if numel(knot)~=r+1 16 | display('Error: Knot vector is not correct size'); 17 | flag = 1; 18 | end 19 | % Find the Basis Function: 20 | if flag == 0 21 | N = Basis(ppoint(3),knot,order,2) 22 | end 23 | %% Generate the Nurbs Curve: 24 | w = double(1/4*ones(1,4)); 25 | for x=1:numel(ppoint) 26 | point = ppoint(x); 27 | temp = Basis(point,knot,order,maxindex)'; 28 | Cu(x) = sum(w .* ptsx .* temp ); 29 | end 30 | %% Plot the Curve: 31 | figure(1), 32 | hold on; 33 | plot(ptsx,ptsy,'ro--'); 34 | title('Nurbs Curve'); 35 | plot(linspace(0,5,numel(ppoint)),Cu,'bx'); 36 | hold off; 37 | -------------------------------------------------------------------------------- /Project/Contents.m: -------------------------------------------------------------------------------- 1 | % Project Files: 2 | % % Test files: 3 | % spheredemo.m % Generates points for a sphere 4 | % surfacedemo.m % Generates points for a surface 5 | % objtester.m % Evaluates the NURBS curve at (ie. this is radomly generated solution that would be initialized by the PSO) 6 | % Nurbstester.m % Evaluates a NURBS curve showing the curve and the blending polynomials 7 | % 8 | % % Nurbs Related Files: 9 | % basisgen.m % Generates the values for the basis functions evaluated at point u (first basis function has errors) 10 | % ikgen.m % Generates random internal knot values for a non-uniform knot vector 11 | % knotgen.m % Generates a knot a non-uniform non-periodic knot vector 12 | % surfacgen.m % Generates the NURBS surface 13 | % 14 | % % PSO Files: 15 | % PSnurbs.m % PSO function for generating nurbs curves 16 | % displayPSO.m % Used in PSO to display the output of the PSO 17 | % objective.m % Objective function for the PSO 18 | % indexer.m % Randomly samples point cloud data to obtain control points -------------------------------------------------------------------------------- /Project/NURBS Paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raazui/MatlabNurbs/7953dd56b618c78c99ab61f8a9b96622717eb284/Project/NURBS Paper.pdf -------------------------------------------------------------------------------- /Project/PSOhelper/NURBS/basisgen.m: -------------------------------------------------------------------------------- 1 | % clc; clear all; close all; 2 | % Generates the B-Spline Basis Function for surface generation: 3 | % t: parameter with value of either U or V: 4 | % Order: Either value of k or l 5 | % Index: (either i or j) containing the index count 6 | % Knot: [r+1x1] Knot vector containing all relevant knots 7 | % Follows the format: 8 | % i = 1 | N(1,1) 9 | % i = 2 | N(2,1) N(2,2) 10 | % i = 3 | N(3,1) N(3,2) N(3,3) 11 | % .... | ..................... 12 | % i = m | N(m,1) N(m,2) N(m,3) .... N(m,order) 13 | % Objective is to find the Diagonal of the matrix N. 14 | function Nk = basisgen(knot,order,t) 15 | % Calculate the number of control points in the desired dimension: 16 | % Create a matrix for storing the values of size [mxorder]: 17 | mplus = numel(knot) - order; 18 | % N = zeros(mplus,order); 19 | for i=1: numel(knot)-1 % Itterate to m+1 points 20 | % Generate linear basis functions: 21 | if ( knot(i) <= t ) && ( knot(i+1)> t ) 22 | N(i,1) = 1; 23 | else 24 | N(i,1) = 0; 25 | end 26 | end 27 | 28 | % Find all non linear basis functions up till the spline degree: 29 | k=2; 30 | count = 1; 31 | while ( k <= order + 1 ) 32 | for i = 1 : mplus 33 | a = k; 34 | temp1 = ( ( t - knot(i) ) / ( knot(i+a-1) - knot(i) ) ) *... 35 | ( N(i,k-1) ); 36 | if i error ) 66 | % Cycle through the population in order to update each particle 67 | for i=1:np 68 | %% Calculate the fittness value for each particle: 69 | cost = costfun(Q,P0(i).iku,P0(i).ikv,P0(i).u,P0(i).v,[P0(i).loc ... 70 | P0(i).w], m,n,k,l); 71 | P0(i).cost = cost; 72 | NFC = NFC + 1; % Update NFC. 73 | Progress = (NFC/maxNFC) * 100 74 | %% P-Best & G-Best: 75 | % Reset the Pbest to the first element in the population upon next 76 | % generation of paticles / itteration of alogirthm. 77 | if cond1 == 1 78 | pbest(loop) = P0(i); 79 | cond1 = 0; 80 | if isempty(gbest) 81 | gbest = pbest(loop); 82 | end 83 | end 84 | % If the particle fittness is better than the generation best 85 | % update the generation best to particle fittness 86 | if pbest(loop).cost > P0(i).cost 87 | pbest(loop) = P0(i); 88 | % G-Best: 89 | % If the particle fittness is better than the global best 90 | % update the generation best to particle fittness 91 | if gbest.cost > pbest(loop).cost 92 | gbest = pbest(loop); 93 | fittest = gbest.cost; 94 | end 95 | end 96 | % Store the gbest values: 97 | if i==np 98 | fittest_value(loop,1) = gbest.cost; 99 | fittest_value(loop,2) = NFC; 100 | end 101 | 102 | %% Calculate equations: 103 | % Calculate w: 104 | wi = Wmax - ( ( ( Wmax - Wmin) * NFC ) / maxNFC ); 105 | %% Calculating the current velocity: 106 | fields = fieldnames(P0); 107 | l1 = rand(1); 108 | l2 = rand(1); 109 | % Update particle velocity: 110 | for a=2 : numel(fields) 111 | if loop==1 112 | v(i,loop).(fields{a}) = c1 * l1 .* ( ... 113 | pbest(loop).(fields{a})... 114 | - P0(i).(fields{a}) ) + c2 * l2 .* ( gbest.(fields{a})... 115 | - P0(i).(fields{a}) ); 116 | else 117 | v(i,loop).(fields{a}) = wi .* v(i,loop-1).(fields{a}) + c1 * l1 .* ( ... 118 | pbest(loop).(fields{a})... 119 | - P0(i).(fields{a}) ) + c2 * l2 .* ( gbest.(fields{a})... 120 | - P0(i).(fields{a}) ); 121 | end 122 | end 123 | for a=2: numel(fields) 124 | %% Update the particles position: 125 | P0(i).(fields{a}) = P0(i).(fields{a}) + v(i,loop).(fields{a}); 126 | % Scale values so they dont exceed thresholds: 127 | if strcmp(fields{a},'w') 128 | temp =abs( P0(i).(fields{a}) ); 129 | o = max(temp); 130 | if o > 2 131 | temp = temp ./ max(temp); 132 | end 133 | P0(i).(fields{a}) = temp; 134 | end 135 | if strcmp(fields{a},'iku') || strcmp(fields{a},'ikv') 136 | temp = abs(P0(i).(fields{a})); 137 | temp( temp<= 0 ) = 0; 138 | temp( temp>= 1 ) = 1; 139 | P0(i).(fields{a}) = sort(temp); 140 | end 141 | if strcmp(fields{a},'u') || strcmp(fields{a},'v') 142 | temp = abs(P0(i).(fields{a})); 143 | temp( temp<= 0 ) = 0; 144 | temp( temp>= 1 ) = 1; 145 | P0(i).(fields{a}) = sort(temp); 146 | end 147 | end 148 | end 149 | 150 | % Update Loop indexing variables: 151 | if NFC > 1 % To Ensure only the proper number of generations are run. 152 | loop = loop + 1; 153 | end 154 | cond1 = 1; % Reset pbest initialization. 155 | end 156 | %% Display the surface: 157 | displayPSO(Q,gbest.iku,gbest.ikv,gbest.u,gbest.v,[gbest.loc ... 158 | gbest.w], m,n,k,l) 159 | %% Plot the error: 160 | figure(2), 161 | plot(fittest_value(:,2),fittest_value(:,1)) 162 | xlabel('Number of Function Calls'); 163 | ylabel('Error') 164 | title('Error of best member vs. Number of Function Calls'); -------------------------------------------------------------------------------- /Project/Reference Paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raazui/MatlabNurbs/7953dd56b618c78c99ab61f8a9b96622717eb284/Project/Reference Paper.pdf -------------------------------------------------------------------------------- /Project/displayPSO.m: -------------------------------------------------------------------------------- 1 | % Displays the surface created from the PSO: 2 | function displayPSO(Q,ikS,ikT,Up,Vq,P,m,n,k,l) 3 | Up = linspace(0,1,1000)'; 4 | Vq = linspace(0,1,1000)'; 5 | S = knotgen(ikS,k); 6 | T = knotgen(ikT,l); 7 | % Generate the knots: 8 | S = knotgen(ikS,k); 9 | T = knotgen(ikT,l); 10 | % Calculate / Generate the surface: 11 | Surface = surfacegen(S,T,Up,Vq,P,m,n,k,l); 12 | Snew = reshape(Surface,size(Up,1)*size(Vq,1),3); 13 | % Plot the surface: 14 | figure(1), 15 | hold on; 16 | plot3(Q(:,1),Q(:,2),Q(:,3),'bO'); 17 | plot3(Snew(:,1),Snew(:,2),Snew(:,3),'rX'); 18 | -------------------------------------------------------------------------------- /Project/objective.m: -------------------------------------------------------------------------------- 1 | % Objective Function for PSnurbs: 2 | function error = objective(Q,ikS,ikT,Up,Vq,P,m,n,k,l) 3 | % Generate the knots: 4 | S = knotgen(ikS,k); 5 | T = knotgen(ikT,l); 6 | % Calculate / Generate the surface: 7 | Surface = surfacegen(S,T,Up,Vq,P,m,n,k,l); 8 | Snew = reshape(Surface,size(Up,1)*size(Vq,1),3); 9 | % size(Q) 10 | % size(Snew) 11 | error =sum( sum( ( Q - Snew ) .^2 ) ); 12 | -------------------------------------------------------------------------------- /Project/test/Nurbstester.m: -------------------------------------------------------------------------------- 1 | % Nurbs Tester: 2 | % This script is meant to test the functionality of the Nurbs functions: 3 | % basisgen.m (Generates B-spline basis functions) 4 | % knotgen.m (Generates Non-uniform non periodic knots. 5 | % surfacegen.m (Generates a surface S(u,v) 6 | clc; clear all; close all; 7 | %% Simple Nurbs Curve: 8 | Points = [ 0 1.5 ; 1 2.6 ; 2 3 ; 3 2 ;2 1]; % Points on a curve 9 | m = 5; % Number of Control points 10 | k = 2; % Curve order - 1 11 | t = linspace(0,1,m); % Parameter for curve 12 | t1 = linspace(0,1,50); % Parameter for generating points 13 | iks = ikgen(m,k); 14 | knot = knotgen(iks,k); 15 | for i = 1: numel(t1) 16 | Nk(i,:) = basisgen( knot , k, t1(i) ); 17 | C(i,1) = sum( ( Points(:,1) .* Nk(i,:)' ) ./ sum( Nk(i,:) ) ); 18 | C(i,2) = sum( ( Points(:,2) .* Nk(i,:)' ) ./ sum( Nk(i,:) ) ); 19 | end 20 | C1 = C(:,1); 21 | C2 = C(:,2); 22 | C1 = C1(isfinite(C1)); 23 | C2 = C2(isfinite(C2)); 24 | figure(1); 25 | hold on; 26 | plot(Points(:,1),Points(:,2),'rO'); 27 | plot(Points(:,1),Points(:,2),'r-'); 28 | plot(C1(:),C2(:),'b'); 29 | grid on; 30 | hold off; 31 | figure(2); 32 | hold on; 33 | color = hsv(size(Nk,2)); 34 | for i = 1 : size(Nk,2) 35 | plot(Nk(:,i),'Color',color(i,:)); 36 | label(i,:) = ['Basis Function: ' num2str(i)]; 37 | end 38 | hold off; 39 | legend(label) -------------------------------------------------------------------------------- /Project/test/objtester.m: -------------------------------------------------------------------------------- 1 | clc; clear all;close all; 2 | % Test Script for PSO objective function: 3 | spheredemo; 4 | % surfacedemo 5 | obj = 'objective'; % Implicit call to the objetive function. 6 | np = 1; % Population Size 7 | %% Initialize the objective function: 8 | costfun = str2func(obj); % Converts the string into a function handle. 9 | %% Population Generation: 10 | % Variables for generating population elements: 11 | % Dimensionality of the problem: 12 | Q = points(1:169,:); % [Nx3] point cloud. 13 | N = size(Q,1); 14 | m = 13; % Size of the control point grid in the ith direction 15 | n = 13; % Size of the control point grid in the jth direction 16 | k = 3; % Maximum curve order for U 17 | l = 3; % Maximum curve order for V 18 | p = 100; % Size of point cloud data generated for error calculation (aplha) 19 | q = 100; % Size of point cloud data generated for error calculation (beta) 20 | nm = m*n; % Number of control points 21 | orderk = [2 6]; % Min Max order possible for U 22 | orderl = [2 6]; % Min Max order possible for V 23 | % Puv(:,:,i) = param(Points,tmat(:,:,i),[]); 24 | % Population vector format: 25 | % P = [P(x,y,z,w) S T]; 26 | for i = 1 : np 27 | % Generate weight vector for each Point in range [0,2]: 28 | P(:,4,i) = ones(nm,1);%2*rand(nm,1); 29 | % Randomly Sample Control Points from Q: 30 | temp = indexer(Q,nm); 31 | P(:,1:3,i) = temp;%indexer(Q,nm); 32 | end 33 | % P = sortrows(P(:,:,1)); 34 | for i = 1 : np 35 | % Generate U: 36 | U(:,i) = linspace(0,1,m)'; 37 | Up(:,i) = linspace(0,1,p)'; 38 | % Generate V: 39 | V(:,i) = linspace(0,1,n)'; 40 | Vq(:,i) = linspace(0,1,q)'; 41 | end 42 | for i = 1 : np 43 | % Generate knot vector for U: 44 | ikS(:,i) = ikgen(m,k)'; 45 | S(:,i) = knotgen(ikS(:,i)',k); 46 | % Generate knot vector for V: 47 | ikT(:,i) = ikgen(n,l)'; 48 | T(:,i) = knotgen(ikT(:,i)',l); 49 | end 50 | % S(2) = 0.5*S(4); 51 | % S(3) = S(4); 52 | % T(2) = 0.5*T(4); 53 | % T(3) = T(4); 54 | % Objective function starts here: 55 | %% Construct Surface: 56 | % First we need to convert the control points into a matrix of size [nxm]: 57 | % for pop = 2 : 1 58 | pop = 1; 59 | Surface(:,:,:) = surfacegen(S(:,pop),T(:,pop),Up(:,pop),Vq(:,pop),... 60 | P(:,:,pop),m,n,k,l); 61 | % end 62 | % Plot the surface 63 | % Plot Point Cloud Data: 64 | figure(1); 65 | hold on; 66 | % error = objective(Q,ikS(:,1)',ikT(:,1)',Up(:,1),Vq(:,1),P(:,:,1),m,n,k,l); 67 | % Plot Generated Surface Points: 68 | for i = 1 : 1 69 | plot3(P(:,1,i),P(:,2,i),P(:,3,i),'b.'); 70 | plot3(Surface(:,:,1,i),Surface(:,:,2,i),Surface(:,:,3,i),'r.'); 71 | end 72 | -------------------------------------------------------------------------------- /Project/test/spheredemo.m: -------------------------------------------------------------------------------- 1 | clc; clear all; close all; 2 | % Sphere Test: 3 | % Reconstructs a sphere to test the PSO-NURBS surface reconstruction 4 | % Algorithm: 5 | %% Construct Sphere: 6 | c = [0 0 0]; % Centriod 7 | r = 1; 8 | x = -4:0.1:4; 9 | y = -4:0.1:4; 10 | z = -4:0.1:4; 11 | c = 1; 12 | for i = 1 : numel(x) 13 | for j = 1 : numel(y) 14 | for k = 1 : numel(z) 15 | result = x(i)^2 + y(j)^2 + z(k)^2; 16 | diff = abs( r^2 - result ); 17 | if diff < 0.01 18 | points(c,1) = x(i); 19 | points(c,2) = y(j); 20 | points(c,3) = z(k); 21 | c = c + 1; 22 | end 23 | end 24 | end 25 | end 26 | % plot3(points(:,1),points(:,2),points(:,3),'r.'); 27 | % p = size(points,1); % Number of points on the sphere surface. 28 | %% Create Control Points: 29 | -------------------------------------------------------------------------------- /Project/test/surfacedemo.m: -------------------------------------------------------------------------------- 1 | % Surface Demo 2 | % Construct Surface: 3 | points =[ 0 0 2.0000; 4 | 3.0000 0 2.0000; 5 | 4.5000 0 7.0000; 6 | 6.5000 0 4.0000; 7 | 8.0000 0 7.0000; 8 | 10.0000 0 9.0000; 9 | 0 10.0000 3.0000; 10 | 3.0000 10.0000 5.0000; 11 | 5.0000 10.0000 8.0000; 12 | 8.0000 10.0000 6.0000; 13 | 10.0000 10.0000 10.0000; 14 | 0 0 2.0000; 15 | 0 3.0000 0; 16 | 0 8.0000 5.0000; 17 | 0 10.0000 3.0000; 18 | 10.0000 0 9.0000; 19 | 10.0000 3.0000 7.0000; 20 | 10.0000 5.0000 7.0000; 21 | 10.0000 8.0000 10.0000; 22 | 10.0000 10.0000 10.0000]; --------------------------------------------------------------------------------