-
Notifications
You must be signed in to change notification settings - Fork 25
/
fig2u3d.m
317 lines (276 loc) · 10.3 KB
/
fig2u3d.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
function [] = fig2u3d(ax, fname, imgtype, addaxes, varargin)
%FIG2U3D Convert figure to U3D file.
% FIG2U3D saves the current axes as a U3D file for inclusion as an
% interactive 3-dimensional figure within a PDF. Either LaTeX or Adobe
% Acrobat can be used to embed the U3D file in the PDF.
%
% A VWS file is also created, which contains the current camera view of
% the axes saved. This file can be used to set the figure's default view
% in the PDF to be the same with the open figure window in MATLAB.
%
% The media9 LaTeX package can import U3D files with their associated VWS
% files in a PDF document. It can be found here:
% http://www.ctan.org/tex-archive/macros/latex/contrib/media9
%
% For PDF readers which do not render 3D figures, it is possible to
% include an alternative 2D image as a substitute to the 3D object.
% For conveniency, the script saves a 2D image together with U3D file.
% File type and other options for exporting this 2D image can be
% specified as additional arguments.
%
% Either export_fig (if available) or the standard print function are
% used for 2D export. Arguments defining 2D export options need conform
% to the export function used.
%
% The IDTF2U3D executables are needed from:
% http://sourceforge.net/projects/u3d/
% To obtain them download:
% http://www.mathworks.com/matlabcentral/fileexchange/25383-matlab-mesh-to-pdf-with-3d-interactive-object
% and place the "bin" directory in the "idtf2u3d" directory of the
% fig2u3d distribution.
%
% usage
% FIG2U3D
% FIG2U3D(ax, fname, imgtype, addaxes, varargin)
%
% optional input
% ax = axes object handle to export (default = gca)
% fname = file name string, e.g. 'myfigure' (default = 'surface')
% Note: Filename extensions are appended automatically.
% imgtype = save axes also as an image, to be used as a substitute in
% PDF readers which cannot render the interactive 3D figure.
% = 'filetype' | 'none'
% where:
% filetype = any file format supported by the export_fig
% or print function (whichever is used)
% 'none' = in this case a 2D image is not saved
% addaxes = show axes in u3d file (default = 0)
% = 0 | 1 (do not show/ show, respectively)
% (depending on which one is available and used).
% varargin = additional options to be passed to print or export_fig
% functions, depending on which one is used for saving the
% 2D image for PDF viewers without 3D support. These must
% conform to the inputs accepted by the export function used.
%
% output
% This M-function does not return any data.
% It saves a U3D file containing the axes object with handle ax.
%
% examples
% peaks
% FIG2U3D(gca, 'peaks', '-dpdf') % if using print
% FIG2U3D(gca, 'peaks', '-dpng', 0, '-r300') % if using print
%
% FIG2U3D(gca, 'peaks', '-pdf') % if using export_fig
% FIG2U3D(gca, 'peaks', '-png') % if using export_fig
%
% remark
% When the axes are unequal, the exporter maintains the aspect ratio by
% changing the exported coordinates to achieve the same view as in the
% MATLAB plot window. To avoid this, edit the "fix_daspect = 1;" line in
% fig2u3d to "fix_daspect = 0;".
%
% dependency
% IDTF2U3D executables, download:
% http://www.mathworks.com/matlabcentral/fileexchange/25383-matlab-mesh-to-pdf-with-3d-interactive-object
% and place the "bin" directory within the "idtf2u3d" directory of the
% fig2u3d distribution.
%
% optional dependency
% export_fig, for saving an accompanying 2D image to substitute the 3D
% inetractive figure in PDF readers which do not render it.
% This can be downloaded from the MATLAB Central File Exchange:
% http://www.mathworks.com/matlabcentral/fileexchange/23629
% Otherwise, the print function is used for the 2D image.
%
% reference
% IDTF (Intermediate Data Text File) Format Description, Version 100,
% Intel Corporation, 2005, available at:
% http://u3d.svn.sourceforge.net/viewvc/u3d/releases/Gold12Update/Docs/IntermediateFormat/IDTF%20Format%20Description.pdf
%
% See also EXAMPLE_FIG2U3D, FIG2PDF3D, FIG2IDTF, IDTF2U3D, VIEW2VWS, PRINT,
% EXPORT_FIG.
%
% File: fig2u3d.m
% Author: Ioannis Filippidis, [email protected]
% Date: 2012.06.10 - 2012.07.26
% Language: MATLAB R2012a
% Purpose: convert figure to U3D file format (lines, surfaces, points)
% Copyright: Ioannis Filippidis, 2012-
% depends
% u3d_pre_surface, u3d_pre_line, u3d_pre_quivergroup, u3d_pre_contourgroup
% fig2idtf, idtf2u3d, view2vws
% axes_extremal_xyz, takehold, restorehold, quivermd, check_file_extension
% optional depends
% export_fig
% known limitations
% surface texturemapping not exported
% filled contourplots not exported
% todo
% use viewmtx
%% input
if nargin < 1
ax = gca;
else
% not a handle ?
if ~ishandle(ax)
warning('fig2u3d:handle',...
'AX argument is not a handle. Exporting current axes.')
ax = gca;
end
% not axes handle ?
handle_type = get(ax, 'Type');
if strcmp(handle_type, 'figure')
warning('fig2u3d:handle',...
['AX argument is a figure handle.',...
'Exporting the first axes child of this figure.'] )
ax = get(ax, 'Children');
end
end
% no axes object ?
if isempty(ax)
warning('fig2u3d:emptyaxes',...
'AX axes handle is empty. Noting to export.')
return
end
% filename provided ?
if nargin < 2
fname = 'surface';
elseif ~ischar(fname) || isempty(fname)
fname = 'surface';
end
% save image substitute ?
saveimg = 1;
if nargin < 3
imgtype = '-png';
elseif strcmp(imgtype, 'none') || isempty(imgtype)
saveimg = 0;
elseif ~ischar(imgtype)
imgtype = '-png';
else
imgtype = '-pdf';
end
% show axes ?
if nargin < 4
addaxes = 0;
elseif isempty(addaxes)
addaxes = 0;
elseif (addaxes ~= 1) && (addaxes ~= 0)
error('fig2u3d:addaxes', 'Argument "addaxes" can be 0 or 1.')
end
plot_axes(ax, addaxes)
delete_idtf = 1; % delete intermediate IDTF file
% nothing in the plot ?
obj = get(ax, 'Children');
if isempty(obj)
warning('axes:empty', 'Nothing in the plot. U3D file not exported.')
return
end
% are the axes equal ?
dar = daspect(ax);
dar = dar /dar(1);
if any(dar ~= 1)
msg = 'Axis aspect ratio unequal. Exported U3D will look different.';
warning('axes:aspect', msg)
end
fix_daspect = 1; % when axes are unequal, change aspect ratio of exported
% graphics, so that the exported figure has the same view
%% convert graphics objects to meshes, line_sets and point_sets
[surf_vertices, surf_faces, surf_facevertexcdata, surf_renderers] = u3d_pre_surface(ax);
[patch_vertices, patch_faces, patch_facevertexcdata, patch_renderers] = u3d_pre_patch(ax);
[line_vertices, line_edges, line_colors,...
line_points, line_point_colors] = u3d_pre_line(ax);
[quiver_vertices, quiver_edges, quiver_colors] = u3d_pre_quivergroup(ax);
[contour_vertices, contour_edges, contour_colors] = u3d_pre_contourgroup(ax);
%% group meshes, line_sets and point_sets
% aggregate meshes
mesh_vertices = [surf_vertices, patch_vertices];
mesh_faces = [surf_faces, patch_faces];
mesh_colors = [surf_facevertexcdata, patch_facevertexcdata];
% aggregate lines
line_vertices = [line_vertices, quiver_vertices, contour_vertices];
line_edges = [line_edges, quiver_edges, contour_edges];
line_colors = [line_colors, quiver_colors, contour_colors];
% aggregate pointsets
pointset_points = line_points;
pointset_colors = line_point_colors;
%% fix axis aspect ratio
if fix_daspect == 1
dar = daspect(ax);
if ~isequal(dar, ones(1, 3) )
msg = ['Unequal axes data aspect ratio, to be fixed by ',...
'scaling the axes. To change this behavior, edit ',...
'"fix_daspect = 1;" in fig2u3d to "fix_daspect = 0;"'];
warning('fig2u3d:daspect', msg)
end
mesh_vertices = axis_rescale(mesh_vertices, dar);
line_vertices = axis_rescale(line_vertices, dar);
pointset_points = axis_rescale(pointset_points, dar);
end
%% export
fig2idtf(fname,...
mesh_vertices, mesh_faces, mesh_colors,...
line_vertices, line_edges, line_colors,...
pointset_points, pointset_colors)
idtf2u3d(fname)
rm_idtf(fname, delete_idtf)
part_renderers = [surf_renderers, patch_renderers];
view2vws(ax, fname, part_renderers, fix_daspect)
save_png_substitute(ax, fname, saveimg, imgtype, varargin{:} )
function rm_idtf(fname, yesno)
if yesno == 0
return
end
% fname extensions ok ?
fname = check_file_extension(fname, '.idtf');
fname = fullfile(cd, fname);
system(['rm ', fname] )
function plot_axes(ax, addaxes)
if addaxes == 0
return
end
[xyz_minmax, dim] = axes_extremal_xyz(ax);
xyz_minmax = 1.3 *xyz_minmax;
x0 = [0, 0, 0].';
vx = [xyz_minmax(2), 0, 0].';
vy = [0, xyz_minmax(4), 0].';
if dim == 3
vz = [0, 0, xyz_minmax(6) ].';
end
held = takehold(ax);
quivermd(ax, x0, vx, 'k')
quivermd(ax, x0, vy, 'k')
quivermd(ax, x0, vz, 'k')
restorehold(ax, held)
function [] = save_png_substitute(ax, fname, saveimg, imgtype, varargin)
% save image substitute ?
if saveimg == 0
return
end
% export_fig available ?
fighandle = get(ax, 'Parent');
if exist('export_fig', 'file') == 2
col = get(fighandle, 'Color'); % current fig background color
% set white background for png ?
if strcmp(imgtype, '-png')
set(fighandle, 'Color', 'w')
end
export_fig(ax, imgtype, varargin{:}, fname)
set(fighandle, 'Color', col) % restore color
else
if strfind(imgtype, 'pdf')
imgtype = '-dpdf';
elseif strfind(imgtype, 'png')
imgtype = '-dpng';
end
print(fighandle, imgtype, varargin{:}, fname)
end
function [a] = axis_rescale(a, dar)
if isempty(a)
return
end
a = cellfun(@(x) cell_divider(x, dar), a, 'UniformOutput', false);
function [x] = cell_divider(x, dar)
x = [x(1, :)/dar(1);
x(2, :)/dar(2);
x(3, :)/dar(3) ];