1function nrb2iges (nurbs, filename) 2% NRB2IGES : Write a NURBS curve or surface to an IGES file. 3% 4% Calling Sequence: 5% 6% nrb2iges (nurbs, filename); 7% 8% INPUT: 9% 10% nurbs : NURBS curve or surface, see nrbmak. 11% filename : name of the output file. 12% 13% Description: 14% 15% The data of the nurbs structure is written in a file following the IGES 16% format. For a more in-depth explanation see, for example: 17% <http://engineeronadisk.com/V2/notes_design/engineeronadisk-76.html>. 18% 19% Copyright (C) 2014 Jacopo Corno 20% 21% This program is free software: you can redistribute it and/or modify 22% it under the terms of the GNU General Public License as published by 23% the Free Software Foundation, either version 3 of the License, or 24% (at your option) any later version. 25 26% This program is distributed in the hope that it will be useful, 27% but WITHOUT ANY WARRANTY; without even the implied warranty of 28% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29% GNU General Public License for more details. 30% 31% You should have received a copy of the GNU General Public License 32% along with this program. If not, see <http://www.gnu.org/licenses/>. 33% 34% This file is based on nurbs2iges.m, (C) 2006 Fu Qiang, originally 35% released under the MIT license. 36 37 dt = datestr (now, 'yyyy.mm.dd'); 38 39 dim = numel (nurbs(1).order); 40 41 % START SECTION 42 S{1} = ''; 43 S{2} = 'IGES obtained from Nurbs toolbox.'; 44 S{3} = 'See <http://octave.sourceforge.net/nurbs/>.'; 45 S{4} = ''; 46 47 % GLOBAL SECTION 48 G{1} = '1H,'; % Parameter Deliminator Character 49 G{2} = '1H;'; % Record Delimiter Character 50 G{3} = HString ('Nurbs toolbox'); % Product ID from Sender 51 G{4} = HString (filename); % File Name 52 G{5} = HString ('Octave Nurbs'); % System ID 53 G{6} = HString ('nrb2iges'); % Pre-processor Version 54 G{7} = '32'; % Number of Bits for Integers (No. of bits present in the integer representation of the sending system) 55 G{8} = '75'; % Single Precision Magnitude (Maximum power of 10 which may be represented as a single precision floating point number from the sending system) 56 G{9} = '6'; % Single Precision Significance (No. of significant digits of a single precision floating point number on the sending system) 57 G{10}= '75'; % Double Precision Magnitude (Maximum power of 10 which may be represented as a double precision floating point number from the sending system) 58 G{11}= '15'; % Double Precision Significance (No. of significant digits of a double precision floating point number on the sending system) 59 G{12}= HString('Nurbs from Octave'); % Product ID for Receiver 60 G{13}= '1.0'; % Model Space Scale 61 G{14}= '6'; % Unit Flag (6 = metres) 62 G{15}= HString('M'); % Units (metres = "M") 63 G{16}= '1000'; % Maximum Number of Line Weights 64 G{17}= '1.0'; % Size of Maximum Line Width 65 G{18}= HString(dt); % Date and Time of file generation 66 G{19}= '0.000001'; % Minimum User-intended Resolution 67 G{20}= '10000.0'; % Approximate Maximum Coordinate 68 G{21}= HString('Jacopo Corno'); % Name of Author 69 G{22}= HString('GSCE - TU Darmstadt'); % Author's Organization 70 G{23}= '3'; % IGES Version Number (3 = IGES version 2.0) 71 G{24}= '0'; % Drafting Standard Code (0 = no standard) 72 73 % Convert section array to lines (maximum lenght 72) 74 SectionG = make_section (G, 72); 75 76 % DIRECTORY ENTRY SECTION 77 % Each directory entry consists of two, 80 character, fixed formatted lines 78 D = []; 79 for ii = 1:length (nurbs) 80 switch (dim) 81 case 1 % NURBS curve 82 D(ii).type = 126; 83 case 2 % NURBS surface 84 D(ii).type = 128; 85 otherwise 86 error ('Only curves and surfaces can be saved in IGES format.') 87 end 88 D(ii).id = 2*ii - 1; % odd counter (see Parameter data section) 89 D(ii).p_start = 0; 90 D(ii).p_count = 0; 91 end 92 93 % PARAMETER DATA SECTION 94 % The structure is a free formatted data entry from columns 1 to 64. 95 % Each line of free formatted data consists of the entity type number 96 % followed by the parameter data describing the entity. 97 % Columns 65 to 72 are reserved for a parameter data index which is an 98 % odd number counter, right justified in the field, which begins at the 99 % number 1 and progresses in odd increments for each entity entered. 100 % Column 73 is reserved for the letter "P" to indicate the data element 101 % belongs to the parameter data section. 102 % Columns 74 to 80 are reserved for the sequence number. Each line of 103 % data corresponds to the entity type as specified in the global section. 104 SectionP = {}; 105 for ii = 1:length (nurbs) 106 P = make_section_array (nurbs(ii)); % finish one entity 107 % Convert section array to lines 108 SP = make_section (P, 64); 109 D(ii).p_count = length (SP); 110 if (ii == 1) 111 D(ii).p_start = 1; 112 else 113 D(ii).p_start = D(ii-1).p_start + D(ii-1).p_count; 114 end 115 SectionP{ii} = SP; 116 end 117 118 % SAVE 119 fid = fopen (filename, 'w'); 120 121 % Save Start Section 122 for ii = 1:length (S) 123 fprintf (fid, '%-72sS%7d\n', S{ii}, ii); 124 end 125 126 % Save Global Section 127 for ii = 1:length (SectionG) 128 fprintf (fid, '%-72sG%7d\n', SectionG{ii}, ii); 129 end 130 131 % Save Directory Entry Section 132 for i = 1:length (D) 133 fprintf (fid, '%8d%8d%8d%8d%8d%8d%8d%8d%8dD%7d\n', ... 134 D(i).type, D(i).p_start, 0, 0 ,0, 0, 0, 0, 0, i*2-1); 135 fprintf (fid, '%8d%8d%8d%8d%8d%8s%8s%8s%8dD%7d\n', ... 136 D(i).type, 0, 0, D(i).p_count, 0, ' ', ' ', ' ', 0, i*2); 137 end 138 139 % Save Parameter Data Section 140 lines_p = 0; 141 for jj = 1:length (D) 142 sec = SectionP{jj}; 143 for ii = 1:length (sec) 144 lines_p = lines_p + 1; 145 fprintf (fid, '%-64s %7dP%7d\n', sec{ii}, D(jj).id, lines_p); 146 end 147 end 148 149 % Save Terminate Section 150 sec_t = sprintf ('%7dS%7dG%7dD%7dP%7d', length (S), length(SectionG), 2*length(D), lines_p); 151 fprintf (fid, '%-72sT%7d\n', sec_t, 1); 152 153 fclose(fid); 154 155end 156 157function P = make_section_array (nurbs) 158 dim = numel (nurbs.order); 159 160 % in IGES the control points are stored in the format [x, y, z, w] 161 % instead of [w*x, w*y, w*z, w] 162 for idim = 1:3 163 nurbs.coefs(idim,:) = nurbs.coefs(idim,:) ./ nurbs.coefs(4,:); 164 end 165 166 P = {}; 167 switch dim 168 case 1 169 % Rational B-Spline Curve Entity 170 cp = nurbs.coefs; 171 deg = nurbs.order - 1; 172 knots = nurbs.knots; 173 uspan = [0 1]; 174 isplanar = ~any(cp(3,:)); 175 P{1} = '126'; % NURBS curve 176 P{2} = int2str (size (cp, 2) - 1); % Number of control points 177 P{3} = int2str (deg); % Degree 178 P{4} = int2str (isplanar); % Curve on xy plane 179 P{5} = '0'; 180 P{6} = '0'; 181 P{7} = '0'; 182 index = 8; 183 for ii = 1:length (knots) 184 P{index} = sprintf ('%f', knots(ii)); 185 index = index + 1; 186 end 187 for ii = 1:size (cp, 2) 188 P{index} = sprintf ('%f', cp(4,ii)); 189 index = index + 1; 190 end 191 for ii = 1:size (cp, 2) 192 P{index} = sprintf ('%f', cp(1,ii)); 193 index = index + 1; 194 P{index} = sprintf ('%f', cp(2,ii)); 195 index = index + 1; 196 P{index} = sprintf ('%f', cp(3,ii)); 197 index = index + 1; 198 end 199 P{index} = sprintf ('%f', uspan(1)); 200 index = index +1; 201 P{index} = sprintf ('%f', uspan(2)); 202 index = index +1; 203 P{index} = '0.0'; 204 index = index +1; 205 P{index} = '0.0'; 206 index = index +1; 207 if isplanar 208 P{index} = '1.0'; 209 else 210 P{index} = '0.0'; 211 end 212 index = index + 1; 213 P{index} = '0'; 214 index = index + 1; 215 P{index} = '0'; 216 case 2 217 % Rational B-Spline Surface Entity 218 cp = nurbs.coefs; 219 degU = nurbs.order(1) - 1; 220 degV = nurbs.order(2) - 1; 221 knotsU = nurbs.knots{1}; 222 knotsV = nurbs.knots{2}; 223 uspan = [0 1]; 224 vspan = [0 1]; 225 P{1} = '128'; % NURBS surface 226 P{2} = int2str (size (cp, 2) - 1); % Number of control points in U 227 P{3} = int2str (size (cp, 3) - 1); % Number of control points in V 228 P{4} = int2str (degU); % Degree in U 229 P{5} = int2str (degV); % Degree in V 230 P{6} = '0'; 231 P{7} = '0'; 232 P{8} = '0'; 233 P{9} = '0'; 234 P{10} = '0'; 235 index = 11; 236 for ii = 1:length (knotsU) 237 P{index} = sprintf ('%f', knotsU(ii)); 238 index = index + 1; 239 end 240 for ii = 1:length (knotsV) 241 P{index} = sprintf ('%f', knotsV(ii)); 242 index = index + 1; 243 end 244 for jj = 1:size (cp, 3) 245 for ii = 1:size (cp, 2) 246 P{index} = sprintf ('%f', cp(4,ii,jj)); 247 index = index + 1; 248 end 249 end 250 for jj = 1:size (cp, 3) 251 for ii = 1:size (cp, 2) 252 P{index} = sprintf ('%f',cp(1,ii,jj)); 253 index = index + 1; 254 P{index} = sprintf ('%f',cp(2,ii,jj)); 255 index = index + 1; 256 P{index} = sprintf ('%f',cp(3,ii,jj)); 257 index = index + 1; 258 end 259 end 260 P{index} = sprintf('%f',uspan(1)); 261 index = index +1; 262 P{index} = sprintf('%f',uspan(2)); 263 index = index +1; 264 P{index} = sprintf('%f',vspan(1)); 265 index = index +1; 266 P{index} = sprintf('%f',vspan(2)); 267 index = index +1; 268 P{index} = '0'; 269 index = index + 1; 270 P{index} = '0'; 271 otherwise 272 273 end 274end 275 276function hs = HString (str) 277% HString : Convert the string STR to the Hollerith format. 278 279 hs = sprintf ('%dH%s', length(str), str); 280end 281 282function sec = make_section (fields, linewidth) 283 sec = {}; 284 index = 1; 285 line = ''; 286 num = length (fields); 287 for i = 1:num 288 if (i < num) 289 newitem = [fields{i} ',']; 290 else 291 newitem = [fields{i} ';']; 292 end 293 len = length (line) + length (newitem); 294 if ( len > linewidth ) 295 % new line 296 sec{index} = line; 297 index = index + 1; 298 line = ''; 299 end 300 line = [line newitem]; 301 end 302 sec{index} = line; 303end 304