image thumbnail

surf to LaTeX

by

 

27 Nov 2006 (Updated )

Converts a displayed surface plot to LaTeX .tex format

surf2latex(fig_handle, st, z_max, z_min)
function surf2latex(fig_handle, st, z_max, z_min)
%% Identification
% David Krause
% Queen's University
% November 26, 2006
% Take a surface plot figure, and create the equivalent LaTeX file
%
% fig_handle - the number of the figure window
% st - a structure with the required parameters
% st.filename - the output filename
% st.comments - a string that has useful comments about the figure
% st.figure_box - 4 element vector specifying [x, y, x_end, y_end] for plot box
% st.figure_mid - A value from 0 to 0.5 specifying how much to leave for
% the z height of the plot
% st.x_tick_width - the weight of the x ticks, 0.25
% st.x_tick_length - the length of the x ticks, 2
% st.x_label_y_offset - for the xlabel, the distance from the box, 8
% st.x_ticklabel_y_offset - for the x tick labels, the distance from the box, 3
% st.y_tick_weight = 0.25;
% st.y_tick_length = 2;
% st.y_label_x_offset = 18;
% st.y_ticklabel_x_offset = 2;
% st.plot_line_width = 0.15;

% Do some initial calculations
home_pos = [(st.figure_box(3) - st.figure_box(1)) / 2 + st.figure_box(1), ...
            st.figure_mid * (st.figure_box(4) - st.figure_box(2)) * 2 + st.figure_box(2)];
x_vec = [-(st.figure_box(3) - st.figure_box(1)) / 2, ...
         -st.figure_mid * (st.figure_box(4) - st.figure_box(2))];
x_vec_unit = x_vec ./ sqrt(x_vec(1) ^ 2 + x_vec(2) ^ 2);

y_vec = [-x_vec(1), x_vec(2)];
y_vec_unit = y_vec ./ sqrt(y_vec(1) ^ 2 + y_vec(2) ^ 2);

z_vec = [0, st.figure_box(4) - st.figure_mid * (st.figure_box(4) - st.figure_box(2)) * 2 - st.figure_box(2)];
z_vec_unit = z_vec ./ sqrt(z_vec(1) ^ 2 + z_vec(2) ^ 2);
     
%% Create the file
[fid, message] = fopen(st.filename, 'w');

% Write the comments
fprintf(fid, '%%Written by surf2latex\n');
fprintf(fid, '%%Author: David Krause\n');
fprintf(fid, '%%Email: david.krause@ece.queensu.ca\n');
fprintf(fid, ['%%Clock output: ', num2str(clock), '\n']);
fprintf(fid, ['%%Comments: ', st.comments, '\n']);

% Write the starting material
fprintf(fid, '\\psset{xunit=1mm,yunit=1mm,runit=1mm}\n');
fprintf(fid, ['\\begin{pspicture}(0,0)(', ...
              num2str(st.figure_box(3) + st.figure_box(1)), ...
              ',', ...
              num2str(st.figure_box(4) + st.figure_box(2)), ')\n']);

% Create the bottom panel
fprintf(fid, ['%% Bottom panel\n']);
temp_pts = [home_pos + x_vec; ...
            home_pos; ...
            home_pos + y_vec; ...
            home_pos + y_vec + x_vec; ...
            home_pos + x_vec];        
write_pspolygon(fid, temp_pts, [0 0 0], [], 0.35);

% Draw the left panel          
fprintf(fid, ['%% Left panel\n']);
temp_pts = [home_pos + x_vec; ...
            home_pos + x_vec + z_vec; ...
            home_pos + z_vec; ...
            home_pos; ...
            home_pos + x_vec];
write_pspolygon(fid, temp_pts, [0 0 0], [], 0.35);

% Draw the right panel
fprintf(fid, ['%% Right panel\n']);
temp_pts = [home_pos + y_vec; ...
            home_pos + y_vec + z_vec; ...
            home_pos + z_vec; ...
            home_pos; ...
            home_pos + y_vec];
write_pspolygon(fid, temp_pts, [0 0 0], [], 0.35);

%% Work with the children of the figure
fig_children = get(fig_handle, 'children');

% For each child, if it is an axes, generate the labels, ticks, and then
% plot the line
for count = 1 : length(fig_children)
    axes_tag = get(fig_children(count), 'Tag');
    axes_type = get(fig_children(count), 'Type');
    if isempty(axes_tag) & strcmp(axes_type, 'axes')
        % Yes, an axes, now get on with it
        fprintf(fid, ['%% Axes handle = ', num2str(fig_children(count)), '\n']);

%% Place the X, Y, and Z axis labels
        % Place the X axis label
        x_label_hnd = get(fig_children(count), 'XLabel');
        if ~isempty(get(x_label_hnd, 'String'));
            temp_pt = home_pos + y_vec + x_vec + y_vec_unit * 13;
            write_rput_text(fid, temp_pt, 'tl', latex2fprintf(get(x_label_hnd, 'String')));
        end
        
        y_label_hnd = get(fig_children(count), 'YLabel');
        if ~isempty(get(y_label_hnd, 'String'));
            temp_pt = home_pos + x_vec + y_vec + x_vec_unit * 13;
            write_rput_text(fid, temp_pt, 'tr', latex2fprintf(get(y_label_hnd, 'String')));
        end
        
        z_label_hnd = get(fig_children(count), 'ZLabel');
        if ~isempty(get(z_label_hnd, 'String'));
            temp_pt = home_pos + x_vec + z_vec * 0.5 + [-15, 0];
            write_rput_text(fid, temp_pt, 'r', latex2fprintf(get(z_label_hnd, 'String')));
        end        

%% Place the X, Y, and Z ticks, labels, and grid lines        
        % Get the XTickLabel from the axes
        x_tick_label = get(fig_children(count), 'XTickLabel');
        % Assuming the labels cover the entire x-axis, place the labels,
        % tick marks and grid lines        
        for x_count = 1 : length(x_tick_label(:, 1))
            if (x_count > 1) & (x_count < length(x_tick_label(:, 1)))
                % Place a tick mark
                temp_pt_start = home_pos + y_vec + x_vec * (x_count - 1) / (length(x_tick_label(:, 1)) - 1);
                temp_pt_stop = temp_pt_start - y_vec_unit * st.x_tick_length;
                write_psline(fid, [temp_pt_start; temp_pt_stop], [0 0 0], 'solidl', st.x_tick_width);
                % Place the grid line
                temp_pt_mid = temp_pt_start - y_vec;
                temp_pt_stop = temp_pt_mid + z_vec;
                write_psline(fid, [temp_pt_start; temp_pt_mid; temp_pt_stop], [0 0 0], 'dotted', st.x_tick_width);
            end
            % Place the label
            temp_pt = home_pos + y_vec + x_vec * (x_count - 1) / (length(x_tick_label(:, 1)) - 1) + y_vec_unit * 3;
            write_rput_text(fid, temp_pt, 'tl', num2str(str2num(x_tick_label(x_count, :))));
            
            % If it is the last tick, see if a power of 10 label is needed
            if x_count == length(x_tick_label(:, 1))
                temp_label = str2num(x_tick_label(x_count, :));
                temp_tick = get(fig_children(count), 'XTick');
                temp_tick = temp_tick(end);
                
                if temp_label == 0
                    temp_label = str2num(x_tick_label(1, :));
                    temp_tick = get(fig_children(count), 'XTick');
                    temp_tick = temp_tick(1);
                end
                
                if round(log10(temp_tick / temp_label)) ~= 0
                    temp_pt = home_pos + y_vec + x_vec * 0.5 + y_vec_unit * 13;
                    write_rput_text(fid, temp_pt, 'tl', ...
                                    ['$\\times 10^{', num2str(round(log10(temp_tick / temp_label))), ...
                                     '}$']);
                end
            end            
        end
        
        % Get the YTickLabel from the axes
        y_tick_label = get(fig_children(count), 'YTickLabel');
        % Assuming the labels cover the entire y-axis, place the labels and
        % tick marks
        for y_count = 1 : length(y_tick_label(:, 1))
            if (y_count > 1) & (y_count < length(y_tick_label(:, 1)))
                % Place a tick mark
                temp_pt_start = home_pos + x_vec + y_vec * (y_count - 1) / (length(y_tick_label(:, 1)) - 1);
                temp_pt_stop = temp_pt_start - x_vec_unit * st.y_tick_length;
                write_psline(fid, [temp_pt_start; temp_pt_stop], [0 0 0], 'solidl', st.y_tick_width);
                % Place the grid line
                temp_pt_mid = temp_pt_start - x_vec;
                temp_pt_stop = temp_pt_mid + z_vec;
                write_psline(fid, [temp_pt_start; temp_pt_mid; temp_pt_stop], [0 0 0], 'dotted', st.y_tick_width);                
            end
            % Place the label            
            temp_pt = home_pos + x_vec + y_vec * (y_count - 1) / (length(y_tick_label(:, 1)) - 1) + x_vec_unit * 3;
            write_rput_text(fid, temp_pt, 'tr', num2str(str2num(y_tick_label(y_count, :))));            

            % If it is the last tick, see if a power of 10 label is needed
            if y_count == length(y_tick_label(:, 1))
                temp_label = str2num(y_tick_label(y_count, :));
                temp_tick = get(fig_children(count), 'YTick');
                temp_tick = temp_tick(end);
                
                if temp_label == 0
                    temp_label = str2num(y_tick_label(1, :));
                    temp_tick = get(fig_children(count), 'YTick');
                    temp_tick = temp_tick(1);
                end
                
                if round(log10(temp_tick / temp_label)) ~= 0
                    temp_pt = home_pos + x_vec + y_vec * 0.5 + x_vec_unit * 13;
                    write_rput_text(fid, temp_pt, 'tr', ...
                                    ['$\\times 10^{', num2str(round(log10(temp_tick / temp_label))), ...
                                     '}$']);
                end
            end            
        end
        
        % Get the ZTickLabel from the axes
        z_tick_label = get(fig_children(count), 'ZTickLabel');
        % Assuming the labels cover the entire Z-axis, place the labels and
        % tick marks
        for z_count = 1 : length(z_tick_label(:, 1))
            if (z_count > 1) & (z_count < length(z_tick_label(:, 1)))
                % Place a tick mark
                temp_pt_start = home_pos + x_vec + z_vec * (z_count - 1) / (length(z_tick_label(:, 1)) - 1);
                temp_pt_stop = temp_pt_start - x_vec_unit * st.z_tick_length;
                write_psline(fid, [temp_pt_start; temp_pt_stop], [0 0 0], 'solidl', st.z_tick_width);
                % Place the grid line
                temp_pt_mid = temp_pt_start - x_vec;
                temp_pt_stop = temp_pt_mid + y_vec;
                write_psline(fid, [temp_pt_start; temp_pt_mid; temp_pt_stop], [0 0 0], 'dotted', st.z_tick_width);                
            end
            % Place the label            
            temp_pt = home_pos + x_vec + z_vec * (z_count - 1) / (length(z_tick_label(:, 1)) - 1) - y_vec_unit * 3;
            write_rput_text(fid, temp_pt, 'r', num2str(str2num(z_tick_label(z_count, :))));            

            % If it is the last tick, see if a power of 10 label is needed
            if z_count == length(z_tick_label(:, 1))
                temp_label = str2num(z_tick_label(z_count, :));
                temp_tick = get(fig_children(count), 'ZTick');
                temp_tick = temp_tick(end);
                
                if temp_label == 0
                    temp_label = str2num(z_tick_label(1, :));
                    temp_tick = get(fig_children(count), 'ZTick');
                    temp_tick = temp_tick(1);
                end
                
                if round(log10(temp_tick / temp_label)) ~= 0
                    temp_pt = home_pos + x_vec * 0.9 + z_vec + z_vec_unit * 8;
                    write_rput_text(fid, temp_pt, 'r', ...
                                    ['$\\times 10^{', num2str(round(log10(temp_tick / temp_label))), ...
                                     '}$']);
                end
            end            
        end

        axes_children = get(fig_children(count), 'Children');
        for child_count = 1 : length(axes_children)
            child_tag = get(axes_children(child_count), 'Tag');
            child_type = get(axes_children(child_count), 'Type');
            x_lim = get(fig_children(count), 'XLim');
            y_lim = get(fig_children(count), 'YLim');
            z_lim = get(fig_children(count), 'ZLim');
            
%% For each surface, plot it!
            if isempty(child_tag) & strcmp(child_type, 'surface')
                % Yes, a surface
                x_data = get(axes_children(child_count), 'XData');
                y_data = get(axes_children(child_count), 'YData');
                z_data = get(axes_children(child_count), 'ZData');
                if isempty(z_max)
                    z_max = max(max(z_data));
                end
                
                if isempty(z_min)
                    z_min = min(min(z_data));
                end
                
                for x_count = 1 : (length(x_data) - 1)
                    for y_count = 1 : (length(y_data) - 1)
                        % First, is the patch within the limits?
                        if (x_data(x_count) >= x_lim(1)) & (x_data(x_count) <= x_lim(2)) & ...
                           (x_data(x_count + 1) >= x_lim(1)) & (x_data(x_count + 1) <= x_lim(2)) & ...
                           (y_data(y_count) >= y_lim(1)) & (y_data(y_count) <= y_lim(2)) & ...
                           (y_data(y_count + 1) >= y_lim(1)) & (y_data(y_count + 1) <= y_lim(2)) & ...
                           (z_data(y_count, x_count) >= z_lim(1)) & (z_data(y_count, x_count) <= z_lim(2)) & ...
                           (z_data(y_count + 1, x_count) >= z_lim(1)) & (z_data(y_count + 1, x_count) <= z_lim(2)) & ...
                           (z_data(y_count, x_count + 1) >= z_lim(1)) & (z_data(y_count, x_count + 1) <= z_lim(2)) & ...
                           (z_data(y_count + 1, x_count + 1) >= z_lim(1)) & (z_data(y_count + 1, x_count + 1) <= z_lim(2))
                            % Yes, the patch is within the limits
                            % Calculate the patch color
                            temp = mean(mean(z_data([y_count, y_count + 1], [x_count, x_count + 1]))) / ...
                                   (z_max - z_min) - z_min / (z_max - z_min);                                
                            if temp <= 0.4
                                temp_rgb = [1, temp / 0.405, 0];
                            elseif (temp > 0.4) & (temp <= 0.5)
                                temp_rgb = [1 - (temp - 0.4) / 0.105, 1, 0];
                            elseif (temp > 0.5) & (temp <= 0.6)
                                temp_rgb = [0, 1, (temp - 0.5) / 0.105];
                            else
                                temp_rgb = [0, 1 - (temp - 0.6) / 0.405, 1];
                            end
                            temp_edge = get(axes_children(child_count), 'EdgeColor');
                            
                            % Calculate the patch points                            
                            pt1 = point_axis_paper(x_data(x_count), y_data(y_count), z_data(y_count, x_count), x_lim, y_lim, z_lim, home_pos, x_vec, y_vec, z_vec);
                            pt2 = point_axis_paper(x_data(x_count + 1), y_data(y_count), z_data(y_count, x_count + 1), x_lim, y_lim, z_lim, home_pos, x_vec, y_vec, z_vec);
                            pt3 = point_axis_paper(x_data(x_count + 1), y_data(y_count + 1), z_data(y_count + 1, x_count + 1), x_lim, y_lim, z_lim, home_pos, x_vec, y_vec, z_vec);
                            pt4 = point_axis_paper(x_data(x_count), y_data(y_count + 1), z_data(y_count + 1, x_count), x_lim, y_lim, z_lim, home_pos, x_vec, y_vec, z_vec);                                                     
                            write_pspolygon(fid, [pt1; pt2; pt3; pt4; pt1], temp_edge, temp_rgb, st.plot_line_width);
                        end
                    end
                end
            end
        end        
    end
end
            
% Write the ending material
fprintf(fid, '\\end{pspicture}\n');

% Close the file
fclose(fid);

Contact us