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);