No BSD License  

Highlights from
igesout

image thumbnail
from igesout by Daniel Claxton
Convert surfaces, curves and lines to IGES file

igesout(obj,filename,varargin)
function igesout(obj,filename,varargin)
% IGESOUT  IGES Converter for points, lines, and Nurbs curves and surfaces
%
%   IGESOUT(OBJ,FILENAME) writes an IGES (*.igs) file with the given
%   FILENAME from an object OBJ.  OBJ can either be an Nx3 array of points,
%   where each column corresponds to X, Y and Z respectively, or a
%   structure describing a NURBS curve or surface.
%  
%   In addition OBJ may also be a cell array containing any combination of
%   the above entities.  IGESOUT will determine which type of IGES entity
%   to encode based on the size and type of input.  Therefore it is not
%   necessary to specify what types of entities are being used.
%
%   IGESOUT(OBJ,FILENAME,'PARAMETER','VALUE') allows the user to set a
%   number of parameter/value pairs listed below
%
%   PARAMETER       DESCRIPTION
%   ---------       ------------------------------------------
%   paramdelim      Parameter Deliminator Character
%   recorddelim     Record Delimiter Character
%   sendid          Product ID from Sender
%   receiveid       Product ID for Receiver
%   filename        File Name
%   systemid        System ID
%   preprocessor    Pre-processor Version
%   intbits         Number of Bits for Integers
%   precision1      Single Precision Magnitude
%   significant1    Single Precision Significance
%   precision2      Double Precision Magnitude
%   significant2    Double Precision Significance
%   scale           Model Space Scale
%   unitflag        Unit Flag (1 = inches, 3 = look to units)
%   units           Model Units 'MM' or 'IN' (Default)
%   lineweights     Maximum number of line weights
%   linewidth       Maximum line width
%   timestamp       Time stamp of creation
%   resolution      Minimum User-inted Resolution
%   max             Approximate Maximum Coordinate
%   author          Author
%   company         Author's Organization
%   version         IGES Version Number
%   standard        Drafting Standard Code (- ANSI)
%   date            Model Creation/Change Date
%
%   The defaults values for each of these parameters is already set within
%   IGESOUT.  It is not necessary to change them, as the default values
%   seem to work fine.  However, it may be prudent for some users to make
%   modifications to these parameters.  For instance, the default value for
%   units is 'IN' (inches).  To change to millimeters set units to 'MM'.
%
%   It should also be noted that igesout also attempts to write the IGES
%   file in the most compact form possible.  This may make the file less
%   readable, but it should minimize overall file size. 
%
%   In order to write Nurbs curves and surfaces to IGES, it will be
%   neccessary to download and install the NURBS toolbox.  It can be found
%   at:
%      http://www.mathworks.com/matlabcentral/fileexchange/
%      <a href="http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=312&objectType=file">NURBS TOOLBOX</a>
%      
%
%   There are no guarantees that this program will work correctly.  It was
%   only tested with ProE and MasterCam, and seemed to work fine for each 
%   of the entities described above.  If you have any problems, please send
%   feedback.
%
%   Example
%   % Works if you have the NURBS toolbox (Saved in current directory)
%   nrb = nrbtestsrf;
%   crv = nrbtestcrv;
%   pline = [0,0,1.1112;0,1.3333,2.1082;0,2.6667,1.6397;0,4,1.3346;];
%   lin = pline(1,:)*3;
%   pt = pline(1,:);
%   igesout({nrb crv pline lin pt},'TestIGES_nurbs')
%
%   % Works if you DON'T have the NURBS toolbox (Saved in current directory)
%   pline = [0,0,1.1112;0,1.3333,2.1082;0,2.6667,1.6397;0,4,1.3346;];
%   lin = pline(1,:)*3;
%   pt = pline(1,:);
%   igesout({pline lin pt},'TestIGES')

% Created by: Daniel Claxton
% dclaxton@ufl.edu
% 15-Mar-2007

% v1.01
% 08-Mar-2009
% Major speed improvements for large files 

% Inspired by: Michael Fassbind's
% NrbsSrf2IGES.m
% 2006


% Format input objects and determine Entity types
[obj,Entity,Num] = getEntities(obj);


% Decompose file name
[path file]=fileparts(filename);

% SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
%                           Start (S-SECTION)
% SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
S = ['Matlab to IGES converter. Written by Daniel Claxton',...
      blanks(21) 'S0000001'];
% SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS





% GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
%                        Setup Header (G-SECTION)
% GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
G.paramdelim     = ',';                           % Parameter Deliminator Character 
G.recorddelim    = ';';                           % Record Delimiter Character
G.sendid         = 'Matlab';                     % Product ID from Sender
G.receiveid      = 'Receiver ID';                 % Product ID for Receiver
G.filename       = [file '.igs'];                 % File Name
G.systemid       = computer;                      % System ID
G.preprocessor   = 'Matlab -> IGES';              % Pre-processor Version
G.intbits        = 16;                            % Number of Bits for Integers
G.precision1     = 06;                            % Single Precision Magnitude
G.significant1   = 15;                            % Single Precision Significance
G.precision2     = 13;                            % Double Precision Magnitude
G.significant2   = 15;                            % Double Precision Significance
G.scale          = 1.0;                           % Model Space Scale
G.unitflag       = 3;                             % Unit Flag (1 = inches, 3 = look to units)
G.units          = 'IN';                          % Model Units 'MM' or 'IN' (Default)
G.lineweights    = 8;                             % Maximum number of line weights
G.linewidth      = 0.016;                         % Maximum line width
G.timestamp      = datestr(now);                  % Time stamp of creation
G.resolution     = 1E-4;                          % Minimum User-inted Resolution
G.max            = getMax(obj);                   % Approximate Maximum Coordinate
G.author         = 'D. Claxton dclaxton@ufl.edu'; % Author
G.company        = 'University of Florida';       % Author's Organization
G.version        = 11;                            % - USPRO/IPO-100 (IGES 5.2) [USPRO93]';  % IGES Version Number  ** prob not right **
G.standard       = 3;                             % - ANSI'; % Drafting Standard Code
G.date           = datestr(now);                  % Model Creation/Change Date

% Check inputs
if nargin < 3
    GG = G;
else
    % Set above parameters from input parameter value pairs
    GG = setParams(G,varargin{:});
end

G = G2str(GG);
% GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG






%PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
%                              P-SECTION
%PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
P = zeros(10,Num);
Data = cell(Num,1);
for i = 1:Num;
    
    if Entity(i) == 126 || Entity(i) == 128
        X = squeeze(obj{i}.coefs(1,:,:));   % Extract X Data
        Y = squeeze(obj{i}.coefs(2,:,:));   % Extract Y Data
        Z = squeeze(obj{i}.coefs(3,:,:));   % Extract Z Data
        W = squeeze(obj{i}.coefs(4,:,:));   % Extract Weights from coefficients

        Coefs = [X(:) Y(:) Z(:)]';
        Weights = W(:);
        Coefs = Coefs(:);        
    end
    
    switch Entity(i)
        case 128
            P(1,i) = Entity(i);             % Entity Type.  128 = Rational spline surface
            P(2,i) = obj{i}.number(1,1)-1;  % Number of points in u direction (doesn't work without -1)
            P(3,i) = obj{i}.number(1,2)-1;  % Number of points in v direction
            P(4,i) = obj{i}.order(1,1)-1;   % Degree_u  (degree = order -1)
            P(5,i) = obj{i}.order(1,2)-1;   % Degree_v
            P(6,i) = 0;                     % PROP1 Closed_u (0 = Not Closed)
            P(7,i) = 0;                     % PROP2 Closed_v (0 = Not Closed) 
            P(8,i) = 0;                     % PROP3 (1 = Polynomial i.e. all weights equal, 0 = rational)***
            P(9,i) = 0;                     % PROP4 1st Direction periodicity (0 = Non-periodic)
            P(10,i)= 0;                     % PROP5 2nd Direction periodicity (0 = Non-periodic)
            Uknots = obj{i}.knots{1}(:);
            Vknots = obj{i}.knots{2}(:);
            Knots = [Uknots; Vknots];
            Data{i} = [Knots; Weights; Coefs];
        case 126            
            P(1,i) = Entity(i);             % Entity Type.  126 = Rational spline curve
            P(2,i) = obj{i}.number - 1;     % Number of points - 1
            P(3,i) = obj{i}.order  - 1;     % Degree of curve
            P(4,i) = 0;                     % PROP1 Planar curve (0 = Not Planar)***
            P(5,i) = 0;                     % PROP2 Closed curve (0 = Not Closed)
            P(6,i) = 0;                     % PROP3 (1 = all weights equal, 0 = rational)***
            P(7,i) = 0;                     % PROP4 Periodic (0 = Not periodic)
            Knots = obj{i}.knots(:);
            Data{i} = [Knots; Weights; Coefs];
        case 106
            P(1,i) = Entity(i);             % Entity Type.  106 = Polyline
            P(2,i) = 2;                     % Planar Polyline (2 = Not Planar)
            P(3,i) = size(obj{i},1);        % Number of points
%             P(4,i) = 0;                     % 
            XYZ = obj{i}';
            Data{i} = XYZ(:);
        case 110
            P(1,i) = Entity(i);  
            XYZ = obj{i}';
            Data{i} = XYZ(:);
        case 116
            P(1,i) = Entity(i);  
            XYZ = obj{i}';
            Data{i} = XYZ(:);
        otherwise
    end
    % *** Note, we choose 0 because it is general case, it just requires us
    %     to write more information to the IGES file. But we can live with 
    %     that to simplify things.



end
[P,L] = P2str(P,Data,GG,Num);
%PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP





% DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
%                               D-SECTION
% DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD

D = zeros(15,Num);
for i=1:Num
    D(1,i) = Entity(i);                 % Entity Type.
    D(2,i) = 1+sum(L(1:i));             % Data Start line
    D(3,i) = 0;                         % Structure
    D(4,i) = 1;                         % Line Font Pattern (1 = Solid)
    D(5,i) = 0;                         % Level
    D(6,i) = 0;                         % View
    D(7,i) = 0;                         % Transformation Matrix
    D(8,i) = 0;                         % Label Display
    D(9,i) = 0;                         % Blank Status (0 = Visible)
    D(10,i)= 0;                         % Subord. Entity Switch (0 = Independant)
    D(11,i)= 0;                         % Entity Use Flag (0 = Geometry)
    D(12,i)= 1;                         % Hierarchy ( 1 = Global defer)
    D(13,i)= 0;                         % Line Weight Number
    D(14,i)= L(i+1);                    % Data end line (Will be set later)
    D(15,i)= 0;                         % Form Number (9 = General Quadratic Surface), 0 = none of above (1-9) options | *Modified Later
end
D = D2str(D);
% DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD






% TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
%                           T - SECTION
% TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
T = [size(S,1),size(G,1),size(D,1),size(P,1)];
T = sprintf('S%07.0fG%07.0fD%07.0fP%07.0f%sT%07.0f',T,blanks(40),1);
% TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

% Check for errors
chk = [size(S); size(G); size(D); size(P); size(T)];
if sum(diff(chk(:,2))) ~= 0
   error(['Something went wrong writing the IGES file: ' file '.igs']) 
end

% Concatenate all Sections
str = [S; G; D; P; T];

% Write to file
fid = fopen([path file '.igs'],'w');
for i=1:size(str,1)-1
    fprintf(fid,'%s\n',str(i,:));
end
fprintf(fid,'%s',str(i+1,:));
if fclose(fid) == 0
    disp([filename '.igs written successfully!']);
end













function [obj,ent,n] = getEntities(obj)
if ~iscell(obj)
    obj = {obj};
end
n = length(obj);
ent = zeros(1,n);
for i=1:n
    if isstruct(obj{i})
        if iscell(obj{i}.knots)
            ent(i) = 128;
        else
            ent(i) = 126;
        end
    else
        [rows] = size(obj{i},1);        
        type = min(rows,3);
        switch type
            case 1
                ent(i) = 116;
            case 2
                ent(i) = 110;
            case 3
                ent(i) = 106;
        end
        
    end
end




function G = setParams(G,p)
n = length(p);
n = n/2;
p = reshape(p,n,2);
for i=1:n
    G = setfield(lower(G,p{i,1}),p{i,2});
end




function s = wrap(str,delim,n)
s = wrapmat(str,delim,n); return

%i = 1;
%while true
%    if length(str) > n
%        tmp = str(1:n);
%        d = findstr(tmp,delim);
%        d = d(end);
%        if d == length(tmp)
%            str = str(n+1:end);
%        else
%            str = [tmp(d+1:end) str(n+1:end)];
%        end
%        tmp = tmp(1:d);
%        tmp(d+1:n) = blanks(n-d);
%        s(i,:) = tmp; %#ok<AGROW>
%        i = i+1;
%    else
%        m = length(str);
%        stop = n - m;
%        tmp = [str blanks(stop)];
%        s(i,:) = tmp; %#ok<AGROW>
%        break
%    end
%end


function str = wrapmat(str,delim,nchar)
% Form the desired regular expression from nchars.
exp = sprintf('(.{1,%d})(?:%c+|$)', nchar-1, delim);

tokens = regexp(str,exp,'tokens');

% Each element if the cell array tokens is single-element cell array 
% containing a string.  Convert this to a cell array of strings.
get_contents = @(f) [f{1} delim];
c = cellfun(get_contents, tokens, 'UniformOutput', false);
c{end}(end) = [];

% Convert cell array into array of strings
str = cell2str(c);

% Insert extra spaces to assure strings are all [nchar] in length
nsrt = nchar-size(str,2);
if nsrt
	str(:,end+nsrt) = ' ';
end




function str = cell2str(c)
% Convert a cell array of strings into an array of strings.
% CELL2STR pads each string in order to force all strings
% have the same length.
%

% Determine the length of each string in cell array c
nblanks = cellfun(@length, c);
maxn = max(nblanks);
nblanks = maxn-nblanks; 

% Create a cell array of blanks.  Each column of the cell array contains
% the number of blanks necessary to pad each row of the converted string
padding = cellfun(@blanks,num2cell(nblanks), 'UniformOutput', false);

% Concatinate cell array and padding
str = {c{:}; padding{:}};

% This operation converts new the cell array into a string
str = [str{:}];

% Reshape the string into an array of strings
ncols = maxn;
nrows = length(str)/ncols;
str = reshape(str,ncols,nrows)';




function str = D2str(D)

k = 1;
[m,n]=size(D);
str = char(zeros(2*n,80-16));
for Nent=1:n
    Entity = D(1,Nent);
        switch Entity
            case 128
            case 126
            case 110
            case 116
            case 106
                D(15,Nent) = 12;   % Change from Copious Data to Linear Curve
            otherwise
        end
    tmp1 = sprintf('%8.0f', D(1:7,Nent));
    tmp2 = sprintf('%8.0f',[D(1,Nent); D(12:15,Nent)]);
    str(k,:)   = [tmp1 blanks(23-8-7)];
    k = k + 1;
    str(k,:) = [tmp2 blanks(39-8-7)];
    k = k + 1;
end

m = size(str,1);
on = true;
count = char(zeros(m,16));
for i=1:m
    if on
        count(i,:) = sprintf('% 8.0fD%07.0f',i,i);
    else
        count(i,:) = sprintf('% 8.0fD%07.0f',0,i);
    end
    on = ~on;
end

str = [str count];


function [str,L] = P2str(P,Data,G,Nentities)
pd = G.paramdelim;
rd = G.recorddelim;
prec = G.precision1;
str = [];
L = zeros(Nentities+1,1);
for Nent=1:Nentities
    switch P(1,Nent)
        case 128
            plen = 1:10;
        case 126
            plen = 1:7;
        case 106
            plen = 1:3;
        case 110
            plen = 1;
        case 116
            plen = 1;
        otherwise
    end
    str1 = sprintf(['%1.0f' pd],P(plen,Nent));
    %precision = sprintf('%d',prec);
    str2 = sprintf(['%1.6f' pd],Data{Nent});
    str3 = ['0., 1., 0., 1.' rd];

    tmp = [str1 str2 str3];
    nsp = 7;

    % Wrap String to be
    tmp = wrap(tmp,pd,71-nsp);

    [m,n] = size(tmp);
    L(Nent+1,1) = m;

    for i=1:n-64
        tmp(:,end+1) = ' '; %#ok<AGROW>
    end
    
    offset = sum(L(1:Nent));
    for j=1:m
        count(j,:) = sprintf('% 8.0fP%07.0f',2*Nent-1,j+offset);
    end

    tmp = [tmp count]; %#ok<AGROW>
    
    str = [str; tmp];
    
    count = []; % Clear count
   
end







function str = G2str(G)
fnames = fieldnames(G);
n = length(fnames);
str = cell(20,1);
pd = G.paramdelim;
rd = G.recorddelim;

k = 1;
for i=1:n
   tmp = getfield(G,fnames{i}); %#ok<GFLD>
   if ischar(tmp)
       tmp = sprintf('%1.0fH%s%s',length(tmp),tmp,pd);
   else
       if tmp-fix(tmp) %#ok<BDLOG>
           tmp = sprintf('%1.6f%s',tmp,pd);
       else
           tmp = sprintf('%1.0f%s',tmp,pd);
       end
   end
   if length(str{k}) + length(tmp) > 79-15
       k = k + 1;
   end
   
   str{k,1} = [str{k} tmp];
   if i == n
       str{k}(end) = rd;
   end
end

last = 0;
while true
    if isempty(str{last+1})
        break
    end
    last = last+1;
end

str = str(1:last,1);
n = length(str{end,1});
stop = 80-8;
str{end}(n+1:stop) = blanks(stop-n);
str = char(str);

count = char(zeros(last,8));
for i=1:last
    count(i,:) = sprintf('G%07.0f',i);
end

str = [str count];



function m = getMax(obj)
m = zeros(1,length(obj));
for i=1:length(obj)
    if isstruct(obj{i})
        m(i) = max(obj{i}.coefs(:));
    else
        m(i) = max(obj{i}(:));
    end
end
m =  max(m);

Contact us at files@mathworks.com