From 0b00e11ffb855253501d3b1ed1e0e2fcc79635f3 Mon Sep 17 00:00:00 2001
From: Yoann Guilhem <yoann.guilhem@esrf.fr>
Date: Fri, 7 Dec 2012 11:06:05 +0000
Subject: [PATCH] Update and add some VTK utility functions

git-svn-id: https://svn.code.sf.net/p/dct/code/trunk@947 4c865b51-4357-4376-afb4-474e03ccb993
---
 zUtil_VTK/gtVTKConvertTypeVTK2Matlab.m |  50 ++++++++++
 zUtil_VTK/gtVTKMeshReader.m            |  52 ++++++----
 zUtil_VTK/gtVTKMeshWriter.m            |  35 ++++---
 zUtil_VTK/gtVTKStructGridWriter.m      | 131 +++++++++++++++++++++++++
 4 files changed, 234 insertions(+), 34 deletions(-)
 create mode 100644 zUtil_VTK/gtVTKConvertTypeVTK2Matlab.m
 create mode 100644 zUtil_VTK/gtVTKStructGridWriter.m

diff --git a/zUtil_VTK/gtVTKConvertTypeVTK2Matlab.m b/zUtil_VTK/gtVTKConvertTypeVTK2Matlab.m
new file mode 100644
index 00000000..cf484518
--- /dev/null
+++ b/zUtil_VTK/gtVTKConvertTypeVTK2Matlab.m
@@ -0,0 +1,50 @@
+function [mType, inFMT, inType] = gtVTKConvertTypeVTK2Matlab(vtkType)
+% GTVTKCONVERTTYPEVTK2MATLAB  Convert VTK datatype to Matlab datatype.
+
+switch vtkType
+case 'unsigned_char'
+    mType  = 'uint8';
+    inFMT  = '%d';
+    inType = 'uchar';
+case 'unsigned_short'
+    mType  = 'uint16';
+    inFMT  = '%d';
+    inType = 'ushort';
+case 'unsigned_int'
+    mType  = 'uint32';
+    inFMT  = '%d';
+    inType = 'uint';
+case 'unsigned_long'
+    mType  = 'uint64';
+    inFMT  = '%d';
+    inType = 'uint64';
+case 'char'
+    mType  = 'int8';
+    inFMT  = '%d';
+    inType = 'schar';
+case 'short'
+    mType  = 'int16';
+    inFMT  = '%d';
+    inType = 'short';
+case 'int'
+    mType  = 'int32';
+    inFMT  = '%d';
+    inType = 'int';
+case 'long'
+    mType  = 'int64';
+    inFMT  = '%d';
+    inType = 'int64';
+case 'float'
+    mType  = 'single';
+    inFMT  = '%f';
+    inType = 'float32';
+case 'double'
+    mType  = 'double';
+    inFMT  = '%f';
+    inType = 'double';
+    otherwise
+        gtError('gtVTKConvertTypeVTK2Matlab:wrong_datatype', ...
+            ['Unimplemented datatype "', vtkType, '", sorry...']);
+end
+
+end % end of function
diff --git a/zUtil_VTK/gtVTKMeshReader.m b/zUtil_VTK/gtVTKMeshReader.m
index 48cf1bd3..ae3b77eb 100644
--- a/zUtil_VTK/gtVTKMeshReader.m
+++ b/zUtil_VTK/gtVTKMeshReader.m
@@ -14,6 +14,18 @@ function mesh = gtVTKMeshReader(filename, varargin)
 %
 %     Version 001 20-10-2012 by YGuilhem yoann.guilhem@esrf.fr
 
+%% Guessing output directory, filename and extension
+[fpath, fname, fext] = fileparts(filename);
+if isempty(fext)
+    fext = '.vtk';
+end
+% Trick to handle ~ path in unix
+if ~isempty(fpath) && isunix && fpath(1)=='~'
+    fpath(1) = '';
+    fpath = fullfile(getenv('HOME'), fpath);
+end
+filename = fullfile(fpath, [fname fext]);
+
 fid = fopen(filename, 'r');
 if fid ==-1
     gtError('gtVTKMeshReader:bad_input_file', 'Can''t open the file.');
@@ -24,7 +36,7 @@ if ~strcmp(file.desc(3:5), 'vtk')
     gtError('gtVTKMeshReader:bad_input_file', 'Not a valid VTK file.');
 end
 
-% Read header, mode and dataset
+%% Read header, mode and dataset
 file.header  = fgets(fid);
 str          = fgets(fid);
 file.mode = sscanf(str, '%s', 1);
@@ -39,7 +51,7 @@ if ~strcmp(file.dataset, 'POLYDATA')
         'This vtk file does not contain PolyData dataset!');
 end
 
-% Read number of vertices and coordinate datatype
+%% Read number of vertices and coordinate datatype
 str = fgets(fid);
 nVert = sscanf(str, 'POINTS %d', 1);
 file.nVertices = nVert;
@@ -50,7 +62,8 @@ if binary
     case {'float', 'double'}
         coordFMT = coordType;
     otherwise
-        true;
+        gtError('gtVTKMeshReader:wrong_coord_type', ...
+            ['cannot handle coordinate with type: ' coordType]);
     end
 else
     switch coordType
@@ -63,41 +76,42 @@ else
     end
 end
 
-% Read vertices
+%% Read vertices
 nCoord = 3*nVert;
 if binary
     coord = fread(fid, nCoord, ['3*' coordFMT '=>' coordFMT], 0 , 'ieee-be');
 else
     [coord, sz] = fscanf(fid, '%f %f %f', nCoord);
     if sz ~= nCoord
-        warning('Problem in reading vertices.');
+        warning('gtVTKMeshReader:vertice_warning', ...
+            'Problem in reading vertices.');
     end
 end
 mesh.vertices = reshape(coord, 3, nVert)';
 
-% Read polygons
+%% Read polygons
 str = fgets(fid);
 while str(1) ~= 'P' %&& str(1) ~= 'V'
     str = fgets(fid);    
 end
 
 if str(1) == 'P'
-    numbers = sscanf(str,'%*s %d %d', 2);
+    numbers = sscanf(str, '%*s %d %d', 2);
     nFace = numbers(1);
     nValue = numbers(2);
     nNode = 3*nFace;
     if binary
         nbytes = 4;
-        type = 'uint32';
         fseek(fid, nbytes, 0);
         connectivity = fread(fid, nValue, '3*int32=>uint32', nbytes, 'ieee-be');
     else
-        connectivity = uint32(fscanf(fid, '%*d %d %d %d\n', nNode));
-        %[connectivity, cnt] = fscanf(fid, '%*d %d %d %d\n', nNode);
-        %if cnt ~= nNode
-        %    warning('Problem in reading faces.');
-        %end
-        %connectivity = uint32(connectivity);
+        [connectivity, cnt] = fscanf(fid, '%*d %d %d %d\n', nNode);
+        if cnt ~= nNode
+            warning('gtVTKMeshReader:face_warning', ...
+                'Problem in reading faces.');
+        end
+        connectivity = uint32(connectivity);
+        class(connectivity)
     end
     mesh.faces = reshape(connectivity+1, 3, nFace)';
 else
@@ -106,21 +120,23 @@ end
 
 % read vertex ids
 %if info == 'V'
-%    nv = sscanf(str,'%*s %d %*s', 1);
+%    nv = sscanf(str, '%*s %d %*s', 1);
 
-%    [A,cnt] = fscanf(fid,'%d %d \n', 2*nv);
+%    [A, cnt] = fscanf(fid, '%d %d \n', 2*nv);
 %    if cnt~=2*nv
-%        warning('Problem in reading faces.');
+%        warning('gtVTKMeshReader:vertex_warning', ...
+%            'Problem in reading vertex.');
 %    end
 
 %    A = reshape(A, 2, cnt/2);
-%    faces = repmat(A(2,:)+1, 3, 1);
+%    faces = repmat(A(2, :)+1, 3, 1);
 %end
 
 %if str(1) ~= 'P' %&& str(1) ~= 'V'
 %    faces = 0;
 %end
 
+%% Close the file end terminate
 fclose(fid);
 
 end % end of function
diff --git a/zUtil_VTK/gtVTKMeshWriter.m b/zUtil_VTK/gtVTKMeshWriter.m
index 1fb68a62..da60e742 100644
--- a/zUtil_VTK/gtVTKMeshWriter.m
+++ b/zUtil_VTK/gtVTKMeshWriter.m
@@ -34,7 +34,7 @@ par.facefield = [];
 par.facecolor = [];
 par = parse_pv_pairs(par, varargin);
 
-% Check coordinate data type
+%% Check coordinate data type
 switch par.coordType
 case {'float', 'double'}
     coordFMT = '%f %f %f\n';
@@ -43,23 +43,23 @@ otherwise
         ['Unsupported coordinates datatype: ' par.coordType]);
 end
 
-% Get file parts and check extension
+%% Get file parts and check extension
 [fpath, fname, fext] = fileparts(filename);
 if isempty(fext)
     fext = '.vtk';
+    filename = fullfile(fpath, [fname fext]);
 elseif ~strcmp(fext, '.vtk')
     gtError('gtVTKMeshWriter:wrong_file_extension', ...
         'Output file extension should be ''.vtk''!');
-    fext = '.vtk';
 end
 
-% Open file for writing
+%% Open file for writing
 fid = fopen(filename, 'w');
 if fid ==-1
     gtError('gtVTKMeshWriter:bad_output_file', 'Can''t open the file.');
 end
 
-% Header
+%% Header
 fprintf(fid, '# vtk DataFile Version 3.0\n');
 fprintf(fid, '%s\n', par.header);
 if par.binary 
@@ -69,20 +69,20 @@ else
 end
 fprintf(fid, 'DATASET POLYDATA\n');
 
-% Points / Vertices
+%% Points / Vertices
 fprintf(fid, 'POINTS %d %s\n', size(mesh.vertices, 1), par.coordType);
 if par.binary
     count = fwrite(fid, mesh.vertices', par.coordType, 0, 'ieee-be');
-    %if count ~= size(mesh.vertices, 1)
     if count ~= numel(mesh.vertices)
-        warning('Problem in writing vertices.');
+        warning('gtVTKMeshWriter:vertice_warning', ...
+            'Problem in writing vertices.');
     end
     fprintf(fid, '\n');
 else
     fprintf(fid, coordFMT, mesh.vertices');
 end
 
-% Polygons / Faces / Cells
+%% Polygons / Faces / Cells
 nFaces = size(mesh.faces, 1);
 nValues = 4*nFaces;
 fprintf(fid, 'POLYGONS %d %d\n', nFaces, nValues);
@@ -90,14 +90,14 @@ output = [3*ones(1, nFaces) ; mesh.faces'-1];
 if par.binary
     count = fwrite(fid, output, 'uint32', 0, 'ieee-be');
     if count ~= nValues
-        warning('Problem in writing faces.');
+        warning('gtVTKMeshWriter:face_warning', 'Problem in writing faces.');
     end
     fprintf(fid, '\n');
 else
     fprintf(fid, '%d %d %d %d\n', output);
 end
 
-% Face field
+%% Face field
 if ~isempty(par.facefield)
     for ifield=1:length(par.facefield)
         fField = par.facefield(ifield);
@@ -127,7 +127,8 @@ if ~isempty(par.facefield)
         if par.binary
             count = fwrite(fid, fField.data, outType, 0, 'ieee-be');
             if count ~= numel(fField.data)
-                warning(['Problem in writing field of face field ''' fField.name '']);
+                warning('gtVTKMeshWriter:face_warning', ...
+                    ['Problem in writing field of face field ''' fField.name '']);
             end
             fprintf(fid, '\n');
         else
@@ -140,7 +141,8 @@ if ~isempty(par.facefield)
             if par.binary
                 count = fwrite(fid, uint8(255*output), 'uchar', 0, 'ieee-be');
                 if count ~= numel(output)
-                    warning(['Problem in writing lookup table of face field ''' fField.name '']);
+                    warning('gtVTKMeshWriter:lookup_table_warning', ...
+                        ['Problem in writing lookup table of face field ''' fField.name '']);
                 end
                 fprintf(fid, '\n');
             else
@@ -150,7 +152,7 @@ if ~isempty(par.facefield)
     end
 end    
 
-% Face color
+%% Face color
 if ~isempty(par.facecolor)
     for ifield=1:length(par.facecolor)
         fField = par.facecolor(ifield);
@@ -171,7 +173,8 @@ if ~isempty(par.facecolor)
         if par.binary
             count = fwrite(fid, uint8(255*output), 'uchar', 0, 'ieee-be');
             if count ~= numel(output)
-                warning(['Problem in writing field of face field ''' fField.name '']);
+                warning('gtVTKMeshWriter:face_field_warning', ...
+                    ['Problem in writing field of face field ''' fField.name '']);
             end
             fprintf(fid, '\n');
         else
@@ -180,7 +183,7 @@ if ~isempty(par.facecolor)
     end
 end    
     
-% Close the file end terminate
+%% Close the file end terminate
 fclose(fid);
 
 end % end of function
diff --git a/zUtil_VTK/gtVTKStructGridWriter.m b/zUtil_VTK/gtVTKStructGridWriter.m
new file mode 100644
index 00000000..6a949395
--- /dev/null
+++ b/zUtil_VTK/gtVTKStructGridWriter.m
@@ -0,0 +1,131 @@
+function gtVTKStructGridWriter(vol, filename, varargin)
+% GTVTKSTRUCTGRIDWRITER  Write a volume in VTK file.
+%
+%   gtVTKStructGridWriter(vol, filename, varargin)
+%   --------------------------------------------------------------------------
+%
+%     INPUT:
+%       vol         =  
+%       filename    = <string>  Path to the output VTK file
+%
+%     OPTIONAL INPUT:
+%       'binary'    = <bool>   Write output in binary format (true by default)
+%       'spacing'   = <double> Vector defining spacing in each space dimension
+%                              ([1 1 1] by default)
+%       'origin'    = <double> Vector defining volume origin
+%                              ([0 0 0] by default)
+%       'header'    = <string> VTK file header description
+%       'datatype'  = <string> Data type to consider for input volume
+%       'cmap'      = <colormap>
+%
+%
+%     Version 001 20-10-2012 by YGuilhem yoann.guilhem@esrf.fr
+
+par.spacing = ones(1, 3);
+par.origin  = zeros(1, 3);
+par.dataname = 'Values';
+par.header   = 'VTK structured volume created by matlabDCT';
+par.datatype = ''; 
+par.cmap = [];
+par.opacity = 1;
+par.verbose = false;
+par.binary = true;
+par = parse_pv_pairs(par, varargin);
+
+if iscell(vol)
+    error('Not implemented: only one volume can be handled by now!');
+else 
+    [nx, ny, nz] = size(vol);
+end
+ntot = nx*ny*nz;
+
+if ~isempty(par.cmap) && size(par.cmap, 1) < max(max(max(vol)))
+    warning('gtVTKStructGridWriter:cmap_warning', ...
+        'You may have not enough values in your cmap...');
+end
+
+%% Guess input & output datatype
+if isempty(par.datatype)
+    par.datatype = class(vol);
+end
+
+[outputTypeVTK, outputType, outputFMT] = gtVTKConvertTypeMatlab2VTK(par.datatype);
+
+if par.verbose
+    disp(['Spacing       : ' num2str(par.spacing)]);
+    disp(['Origin        : ' num2str(par.origin)]);
+    disp(['Color map     : ' num2str(par.cmap)]);
+    disp(['Dataname      : ' par.dataname]);
+    disp(['Header        : ' par.header]);
+    disp(['OutputType    : ' outputType]);
+    disp(['OutputTypeVTK : ' outputTypeVTK]);
+end
+
+%% Open the file
+fid = fopen(filename, 'w');
+if fid ==-1
+    gtError('gtVTKStructGridWriter:bad_output_file', 'Can''t open the file.');
+end
+
+%% Write ASCII file header
+fprintf(fid, '# vtk DataFile Version 3.0\n');
+fprintf(fid, '%s\n', par.header);
+if par.binary 
+    fprintf(fid, 'BINARY\n');
+else
+    fprintf(fid, 'ASCII\n');
+end
+fprintf(fid, 'DATASET STRUCTURED_POINTS\n');
+fprintf(fid, 'DIMENSIONS %d %d %d\n', nx, ny, nz);
+fprintf(fid, 'ORIGIN  %4.3f   %4.3f  %4.3f\n', par.origin);
+fprintf(fid, 'SPACING %4.3f   %4.3f  %4.3f\n', par.spacing);
+
+fprintf(fid, 'POINT_DATA %d\n', ntot);
+fprintf(fid, 'SCALARS %s %s\n', par.dataname, outputTypeVTK);
+
+if ~isempty(par.cmap)
+    fprintf(fid, 'LOOKUP_TABLE map\n');
+else
+    fprintf(fid, 'LOOKUP_TABLE default\n');
+end
+
+%% Write volume data
+if par.binary 
+    count = fwrite(fid, reshape(vol, 1, ntot), par.datatype, 0, 'ieee-be');
+    if count ~= numel(vol)
+        warning('gtVTKStructGridWriter:structgrid_volume_warning', ...
+            'Problem in writing structured grid volume.');
+    end
+    fprintf(fid, '\n');
+else
+    fprintf(fid, [outputFMT '\n'], reshape(vol, 1, ntot));
+end
+
+%% Write lookup table if needed
+if ~isempty(par.cmap)
+    mapSize = size(par.cmap);
+    if mapSize(2) == 3
+        output = [par.cmap'; par.opacity*ones(1, mapSize(1))];
+    elseif mapSize(2) == 4
+        output = par.cmap';
+    else
+        gtError('gtVTKStructGridWriter:wrong_cmap_size', ...
+            'Color map sould be N row vector of size 3 or 4!');
+    end
+    fprintf(fid, 'LOOKUP_TABLE map %d\n', mapSize(1));
+    if par.binary
+        count = fwrite(fid, uint8(225*output), 'uchar', 0, 'ieee-be');
+        if count ~= numel(output)
+            warning('gtVTKMeshWriter:cmap_warning', ...
+                'Problem in writing color map!');
+        end
+        fprintf(fid, '\n');
+    else
+        fprintf(fid, '%f %f %f %f\n', output);
+    end
+end
+
+%% Close file and terminate
+fclose(fid);
+
+end % end of function
-- 
GitLab