/code/plot2svg.m

https://github.com/hananel/piggottDesignCode · Objective C · 3079 lines · 3032 code · 47 blank · 0 comment · 588 complexity · d8b3bad0a49ffca9f1c0f150d16951b8 MD5 · raw file

Large files are truncated click here to view the full file

  1. function varargout = plot2svg(param1,id,pixelfiletype)
  2. % Matlab to SVG converter
  3. % Prelinary version supporting 3D plots as well
  4. %
  5. % Usage: plot2svg(filename,graphic handle,pixelfiletype)
  6. % optional optional optional
  7. % or
  8. %
  9. % plot2svg(figuresize,graphic handle,pixelfiletype)
  10. % optional optional optional
  11. %
  12. % pixelfiletype = 'png' (default), 'jpg'
  13. %
  14. % Juerg Schwizer 23-Oct-2005
  15. % See http://www.zhinst.com/blogs/schwizer/ to get more informations
  16. %
  17. % 07.06.2005 - Bugfix axxindex (Index exceeds matrix dimensions)
  18. % 19.09.2005 - Added possibility to select output format of pixel graphics
  19. % 23.10.2005 - Bugfix cell array strings (added by Bill)
  20. % Handling of 'hggroups' and improved grouping of objects
  21. % Improved handling of pixel images (indexed and true color pictures)
  22. % 23.10.2005 - Switched default pixelfromat to 'png'
  23. % 07.11.2005 - Added handling of hidden axes for annotations (added by Bill)
  24. % 03.12.2005 - Bugfix of viewBox to make Firefox 1.5 working
  25. % 04.12.2005 - Improved handling of exponent values for log-plots
  26. % Improved markers
  27. % 09.12.2005 - Bugfix '<' '>' '?' '"'
  28. % 22.12.2005 - Implementation of preliminary 3D version
  29. % Clipping
  30. % Minor tick marks
  31. % 22.01.2005 - Removed unused 'end'
  32. % 29.10.2006 - Bugfix '°','ą','ľ','˛','ł','ź''˝','ž','Š''Ž'
  33. % 17-04-2007 - Bugfix 'projection' in hggroup and hgtransform
  34. % 27-01-2008 - Added Octave functionality (thanks to Jakob Malm)
  35. % Bugfixe cdatamapping (thanks to Tom)
  36. % Bugfix image data writing (thanks to Tom)
  37. % Patches includes now markers as well (needed for 'scatter'
  38. % plots (thanks to Phil)
  39. % 04-02-2008 - Bugfix markers for Octave (thanks to Jakob Malm)
  40. % 30-12-2008 - Bugfix image scaling and orientation
  41. % Bugfix correct backslash (thanks to Jason Merril)
  42. % 20-06-2009 - Improvment of image handling (still some remaining issues)
  43. % Fix for -. line style (thanks to Ritesh Sood)
  44. % 28-06-2009 - Improved depth sorting for patches and surface
  45. % - Bugfix patches
  46. % - Bugfix 3D axis handling
  47. % 11-07-2009 - Support of FontWeight and FontAngle properties
  48. % - Improved markers (polygon instead of polyline for closed markers)
  49. % - Added character encoding entry to be fully SVG 1.1 conform
  50. % 13-07-2009 - Support of rectangle for 2D
  51. % - Added preliminary support for SVG filters
  52. % - Added preliminary support for clipping with pathes
  53. % - Added preliminary support for turning axis tickmarks
  54. % 18-07-2009 - Line style scaling with line width (will not match with png
  55. % output)
  56. % - Small optimizations for the text base line
  57. % - Bugfix text rotation versus shift
  58. % - Added more SVG filters
  59. % - Added checks for filter strings
  60. % 21-07-2009 - Improved bounding box calculation for filters
  61. % - Bugfixes for text size / line distance
  62. % - Support of background box for text
  63. % - Correct bounding box for text objects
  64. % 31-07-2009 - Improved support of filters
  65. % - Experimental support of animations
  66. % 16-08-2009 - Argument checks for filters
  67. % - Rework of latex string handling
  68. % - 'sub' and 'super' workaround for Firefox and Inkscape
  69. % 31-10-2009 - Bugfix for log axes (missing minor grid for some special
  70. % cases)
  71. % 24-01-2010 - Bugfix nomy line #1102 (thanks to Pooya Jannaty)
  72. % 17-02-2010 - Bugfix minor tickmarks for log axis scaling (thanks to
  73. % Harke Pera)
  74. % - Added more lex symbols
  75. % 06-03-2010 - Automatic correction of illegal axis scalings by the user
  76. % (thanks to Juergen)
  77. % - Renamed plot2svg_beta to plot2svg
  78. % 12-04-2010 - Improved Octave compatibility
  79. % 05-05-2010 - Bugfix for ticklabels outside of the axis limits (thanks to
  80. % Ben Scandella)
  81. % 30-10-2010 - Improved handling of empty cells for labels (thanks to
  82. % Constantine)
  83. % - Improved HTML character coding (thanks to David Mack)
  84. % - Bugfix for last ')' (thanks to Jonathon Harding and Benjamin)
  85. % - Enabled scatter plots using hggroups
  86. % - Closing patches if they do not contain NaNs
  87. % 10-11-2010 - Support of the 'Layer' keyword to but the grid on top of
  88. % of the other axis content using 'top' (Many thanks to Justin
  89. % Ashmall)
  90. % - Tiny optimization of the grid display at axis borders
  91. global PLOT2SVG_globals
  92. global colorname
  93. progversion='10-Nov-2010';
  94. PLOT2SVG_globals.runningIdNumber = 0;
  95. PLOT2SVG_globals.octave = false;
  96. PLOT2SVG_globals.checkUserData = true;
  97. if nargout==1
  98. varargout={0};
  99. end
  100. disp([' Matlab/Octave to SVG converter version ' progversion ', Juerg Schwizer (converter@bluewin.ch).'])
  101. matversion=version;
  102. if exist('OCTAVE_VERSION','builtin')
  103. PLOT2SVG_globals.octave = true;
  104. disp(' Info: PLOT2SVG runs in Octave mode.')
  105. else
  106. if str2num(matversion(1))<6 % Check for matlab version and print warning if matlab version lower than version 6.0 (R.12)
  107. disp(' Warning: Future versions may no more support older versions than MATLAB R12.')
  108. end
  109. end
  110. if nargout > 1
  111. error('Function returns only one return value.')
  112. end
  113. if nargin<2 % Check if handle was included into function call, otherwise take current figure
  114. id=gcf;
  115. end
  116. if nargin==0
  117. if PLOT2SVG_globals.octave
  118. error('PLOT2SVG in Octave mode does not yet support a file menu. File name is needed during function call.')
  119. else
  120. [filename, pathname] = uiputfile( {'*.svg', 'SVG File (*.svg)'},'Save Figure as SVG File');
  121. if ~( isequal( filename, 0) || isequal( pathname, 0))
  122. % yes. add backslash to path (if not already there)
  123. pathname = addBackSlash( pathname);
  124. % check, if extension is allrigth
  125. if ( ~strcmpi( getFileExtension( filename), '.svg'))
  126. filename = [ filename, '.svg'];
  127. end
  128. finalname=[pathname filename];
  129. else
  130. disp(' Cancel button was pressed.')
  131. return
  132. end
  133. end
  134. else
  135. if isnumeric(param1)
  136. if PLOT2SVG_globals.octave
  137. error('PLOT2SVG in Octave mode does not yet support a file menu. File name is needed during function call.')
  138. else
  139. [filename, pathname] = uiputfile( {'*.svg', 'SVG File (*.svg)'},'Save Figure as SVG File');
  140. if ~( isequal( filename, 0) || isequal( pathname, 0))
  141. % yes. add backslash to path (if not already there)
  142. pathname = addBackSlash( pathname);
  143. % check, if ectension is allrigth
  144. if ( ~strcmpi( getFileExtension( filename), '.svg'))
  145. filename = [ filename, '.svg'];
  146. end
  147. finalname=[pathname filename];
  148. else
  149. disp(' Cancel button was pressed.')
  150. return
  151. end
  152. end
  153. else
  154. finalname=param1;
  155. end
  156. end
  157. % needed to see annotation axes
  158. originalShowHiddenHandles = get(0, 'ShowHiddenHandles');
  159. set(0, 'ShowHiddenHandles', 'on');
  160. originalFigureUnits=get(id,'Units');
  161. set(id,'Units','pixels'); % All data in the svg-file is saved in pixels
  162. paperpos=get(id,'Position');
  163. if ( nargin > 0)
  164. if isnumeric(param1)
  165. paperpos(3)=param1(1);
  166. paperpos(4)=param1(2);
  167. end
  168. end
  169. if (nargin < 3)
  170. PLOT2SVG_globals.pixelfiletype = 'png';
  171. else
  172. PLOT2SVG_globals.pixelfiletype = pixelfiletype;
  173. end
  174. cmap=get(id,'Colormap');
  175. colorname='';
  176. for i=1:size(cmap,1)
  177. colorname(i,:)=sprintf('%02x%02x%02x',fix(cmap(i,1)*255),fix(cmap(i,2)*255),fix(cmap(i,3)*255));
  178. end
  179. % Open SVG-file
  180. [pathstr,name,ext,versn] = fileparts(finalname);
  181. %PLOT2SVG_globals.basefilename = fullfile(pathstr,name);
  182. PLOT2SVG_globals.basefilepath = pathstr;
  183. PLOT2SVG_globals.basefilename = name;
  184. PLOT2SVG_globals.figurenumber = 1;
  185. fid=fopen(finalname,'wt'); % Create a new text file
  186. fprintf(fid,'<?xml version="1.0" encoding="utf-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n'); % Insert file header
  187. fprintf(fid,'<svg preserveAspectRatio="xMinYMin meet" width="100%%" height="100%%" viewBox="0 0 %0.3f %0.3f" ',paperpos(3),paperpos(4));
  188. fprintf(fid,' version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"');
  189. %fprintf(fid,' onload="Init(evt)"');
  190. fprintf(fid,'>\n');
  191. fprintf(fid,' <desc>Matlab Figure Converted by PLOT2SVG written by Juerg Schwizer</desc>\n');
  192. %fprintf(fid,' <script type="text/ecmascript" xlink:href="puzzle_script.js" />\n');
  193. fprintf(fid,' <g id="topgroup">\n');
  194. group=1;
  195. groups=[];
  196. axfound=0;
  197. % Frame of figure
  198. figcolor = searchcolor(id,get(id, 'Color'));
  199. if (~ strcmp(figcolor, 'none'))
  200. % Draw rectangle in the background of the graphic frame to cover all
  201. % other graphic elements
  202. try % Octave does not have support for InvertHardcopy yet -- Jakob Malm
  203. if strcmp(get(id,'InvertHardcopy'),'on')
  204. fprintf(fid,' <rect x="0" y="0" width="%0.3f" height="%0.3f" fill="#ffffff" stroke="none" />\n',paperpos(3),paperpos(4));
  205. else
  206. fprintf(fid,' <rect x="0" y="0" width="%0.3f" height="%0.3f" fill="%s" stroke="none" />\n',paperpos(3),paperpos(4),figcolor);
  207. end
  208. catch
  209. fprintf(fid,' <rect x="0" y="0" width="%0.3f" height="%0.3f" fill="%s" stroke="none" />\n',paperpos(3),paperpos(4),figcolor);
  210. end
  211. end
  212. % Search all axes
  213. ax=get(id,'Children');
  214. for j=length(ax):-1:1
  215. currenttype = get(ax(j),'Type');
  216. if strcmp(currenttype,'axes')
  217. group=group+1;
  218. groups=[groups group];
  219. group=axes2svg(fid,id,ax(j),group,paperpos);
  220. axfound=1;
  221. elseif strcmp(currenttype,'uicontrol')
  222. if strcmp(get(ax(j),'Visible'),'on')
  223. control2svg(fid,id,ax(j),group,paperpos);
  224. axfound=1;
  225. end
  226. elseif strcmp(currenttype, 'uicontextmenu') || ...
  227. strcmp(currenttype, 'uimenu') || ...
  228. strcmp(currenttype, 'hgjavacomponent') || ...
  229. strcmp(currenttype, 'uitoolbar')
  230. % ignore these types
  231. else
  232. disp([' Warning: Unhandled main figure child type: ' currenttype]);
  233. end
  234. end
  235. fprintf(fid,' </g>\n');
  236. fprintf(fid,'</svg>\n');
  237. fclose(fid); % close text file
  238. if nargout==1
  239. varargout={0};
  240. end
  241. set(id,'Units',originalFigureUnits);
  242. set(0, 'ShowHiddenHandles', originalShowHiddenHandles);
  243. function clippingIdString = clipping2svg(fid, id, ax, paperpos, axpos, projection, clippingIdString)
  244. global PLOT2SVG_globals
  245. if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData'))
  246. struct_data = get(id,'UserData');
  247. if isfield(struct_data,'svg')
  248. if isfield(struct_data.svg,'ClippingPath')
  249. clip = struct_data.svg.ClippingPath;
  250. if ~isempty(clip)
  251. if size(clip, 2) ~=3
  252. if size(clip, 2) ==2
  253. clipx = clip(:, 1);
  254. clipy = clip(:, 2);
  255. clipz = zeros(size(clip,1),1);
  256. else
  257. error('The clipping vector has to be a nx3 or nx2 matrix.');
  258. end
  259. else
  260. clipx = clip(:, 1);
  261. clipy = clip(:, 2);
  262. clipz = clip(:, 3);
  263. end
  264. if strcmp(get(ax,'XScale'),'log')
  265. clipx(find(clipx<=0)) = NaN;
  266. clipx=log10(clipx);
  267. end
  268. if strcmp(get(ax,'YScale'),'log')
  269. clipy(find(clipy<=0)) = NaN;
  270. clipy=log10(clipy);
  271. end
  272. if strcmp(get(ax,'ZScale'),'log')
  273. clipz(find(clipz<=0)) = NaN;
  274. clipz=log10(clipz);
  275. end
  276. [x,y,z] = project(clipx,clipy,clipz,projection);
  277. x = (x*axpos(3)+axpos(1))*paperpos(3);
  278. y = (1-(y*axpos(4)+axpos(2)))*paperpos(4);
  279. clippingIdString = createId;
  280. fprintf(fid,'<clipPath id="%s">\n <polygon fill="none" stroke="none" points="', clippingIdString);
  281. fprintf(fid,'%0.3f,%0.3f ',[x';y']);
  282. fprintf(fid,'"/>\n</clipPath>\n');
  283. end
  284. end
  285. end
  286. end
  287. function [angle, align] = improvedXLabel(id, angle, align)
  288. global PLOT2SVG_globals
  289. if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData'))
  290. struct_data = get(id,'UserData');
  291. if isfield(struct_data,'svg')
  292. if isfield(struct_data.svg,'XTickLabelAngle')
  293. angle = struct_data.svg.XTickLabelAngle;
  294. align = 'Left';
  295. end
  296. end
  297. end
  298. function [angle, align] = improvedYLabel(id, angle, align)
  299. global PLOT2SVG_globals
  300. if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData'))
  301. struct_data = get(id,'UserData');
  302. if isfield(struct_data,'svg')
  303. if isfield(struct_data.svg,'YTickLabelAngle')
  304. angle = struct_data.svg.YTickLabelAngle;
  305. align = 'Left';
  306. end
  307. end
  308. end
  309. function animation2svg(fid, id)
  310. global PLOT2SVG_globals
  311. if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData'))
  312. struct_data = get(id,'UserData');
  313. if isfield(struct_data,'svg')
  314. if isfield(struct_data.svg,'Animation')
  315. animation = struct_data.svg.Animation;
  316. for i = 1:length(animation)
  317. if ~isfield(animation(i).SubAnimation, 'Type')
  318. error(['Missing field ''Type'' for animation.']);
  319. end
  320. switch animation(i).SubAnimation.Type
  321. case 'Opacity', type = 'opacity'; animationType = 0;
  322. case 'Translate', type = 'translate'; animationType = 2;
  323. case 'Scale', type = 'scale'; animationType = 2;
  324. case 'Rotate', type = 'rotate'; animationType = 1;
  325. case 'skewX', type = 'skewX'; animationType = 1;
  326. case 'skewY', type = 'skewY'; animationType = 1;
  327. otherwise, error(['Unknown animation type ''' animation(i).SubAnimation.Type '''.']);
  328. end
  329. %fprintf(fid,' <animate attributeType="XML" attributeName="%s" from="%0.3f" to="%0.3f" dur="%0.3fs" repeatCount="%s" />',...
  330. % 'opacity' , 0, 1, 5, 'indefinite');
  331. if animationType == 0
  332. fprintf(fid,' <animate attributeType="XML" attributeName="%s" dur="%0.3fs"', type, animation(i).SubAnimation.Duration);
  333. fprintf(fid,' values="');
  334. fprintf(fid,'%0.2f;', animation(i).SubAnimation.Value);
  335. fprintf(fid,'" keyTimes="');
  336. fprintf(fid,'%0.2f;', max(min(animation(i).SubAnimation.Key, 1), 0));
  337. fprintf(fid,'" repeatCount="%s" calcMode="linear" />', 'indefinite');
  338. elseif animationType == 1
  339. fprintf(fid,' <animateTransform attributeName="transform" attributeType="XML" type="%s" dur="%0.3fs"', type, animation(i).SubAnimation.Duration);
  340. fprintf(fid,' values="');
  341. fprintf(fid,'%0.2f;', animation(i).SubAnimation.Value);
  342. fprintf(fid,'" keyTimes="');
  343. fprintf(fid,'%0.2f;', max(min(animation(i).SubAnimation.Key, 1), 0));
  344. fprintf(fid,'" repeatCount="%s" calcMode="linear" additive="sum" />', 'indefinite');
  345. elseif animationType == 2
  346. fprintf(fid,' <animateTransform attributeName="transform" attributeType="XML" type="%s" dur="%0.3fs"', type, animation(i).SubAnimation.Duration);
  347. fprintf(fid,' values="');
  348. fprintf(fid,'%0.2f,%0.2f;', animation(i).SubAnimation.Value);
  349. fprintf(fid,'" keyTimes="');
  350. fprintf(fid,'%0.2f;', max(min(animation(i).SubAnimation.Key, 1), 0));
  351. fprintf(fid,'" repeatCount="%s" calcMode="linear" additive="sum" />', 'indefinite');
  352. end
  353. end
  354. end
  355. end
  356. end
  357. function [filterString, boundingBox] = filter2svg(fid, id, boundingBoxAxes, boundingBoxElement)
  358. global PLOT2SVG_globals
  359. filterString = '';
  360. boundingBox = boundingBoxAxes;
  361. if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData'))
  362. struct_data = get(id,'UserData');
  363. if isfield(struct_data,'svg')
  364. boundingBox = boundingBoxElement;
  365. absolute = true;
  366. offset = 0;
  367. if isfield(struct_data.svg,'BoundingBox')
  368. if isfield(struct_data.svg.BoundingBox, 'Type')
  369. switch struct_data.svg.BoundingBox.Type
  370. case 'axes', boundingBox = boundingBoxAxes; absolute = true;
  371. case 'element', boundingBox = boundingBoxElement; absolute = true;
  372. case 'relative', boundingBox = boundingBoxElement; absolute = false;
  373. otherwise
  374. error(['Unknown bounding box type ''' struct_data.svg.BoundingBox.Type '''.']);
  375. end
  376. end
  377. if isfield(struct_data.svg.BoundingBox, 'Overlap')
  378. overlap = struct_data.svg.BoundingBox.Overlap;
  379. if absolute
  380. boundingBox(1) = boundingBox(1) - overlap;
  381. boundingBox(2) = boundingBox(2) - overlap;
  382. boundingBox(3) = boundingBox(3) + 2 * overlap;
  383. boundingBox(4) = boundingBox(4) + 2 * overlap;
  384. else
  385. boundingBox(1) = boundingBox(1) - boundingBox(3) * overlap;
  386. boundingBox(2) = boundingBox(2) - boundingBox(4) * overlap;
  387. boundingBox(3) = boundingBox(3) + 2 * boundingBox(3) * overlap;
  388. boundingBox(4) = boundingBox(4) + 2 * boundingBox(4) * overlap;
  389. end
  390. end
  391. if isfield(struct_data.svg.BoundingBox, 'Visible') && strcmp(struct_data.svg.BoundingBox.Visible, 'on')
  392. % This functionality is very interesting for debugging of
  393. % bounding boxes of filters
  394. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="#000000" stroke-dasharray="1pt,1pt" stroke-width="0.2pt" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  395. end
  396. end
  397. if isfield(struct_data.svg,'Filter')
  398. % Predefined filter sources. Additional filter sources will be
  399. % added later.
  400. predefinedSources = {'SourceGraphic','SourceAlpha','BackgroundImage','BackgroundAlpha','FillPaint','StrokePaint'};
  401. resultStrings = predefinedSources;
  402. filterId = createId;
  403. filterString = ['filter="url(#' filterId ')"'];
  404. fprintf(fid,'<defs>\n');
  405. fprintf(fid,' <filter x="%0.3f%%" y="%0.3f%%" width="%0.3f%%" height="%0.3f%%" id="%s">\n', 0, 0, 100, 100, filterId);
  406. %if absolute
  407. % fprintf(fid,' <filter x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" filterUnits="userSpaceOnUse" id="%s">\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4), filterId);
  408. %else
  409. % fprintf(fid,' <filter x="%0.3f%%" y="%0.3f%%" width="%0.3f%%" height="%0.3f%%" id="%s">\n', -(offset * 100), -(offset * 100), 100 + (offset * 200), 100 + (offset * 200), filterId);
  410. % % Note: use default -10% for attribute x
  411. % % use default -10% for attribute y
  412. % % use default 120% for attribute width
  413. % % use default 120% for attribute height
  414. %end
  415. filter = struct_data.svg.Filter;
  416. for i = 1:length(filter)
  417. if isfield(filter(i).Subfilter, 'Type')
  418. fprintf(fid,' <%s', filter(i).Subfilter.Type);
  419. else
  420. error(['Missing field ''Type'' for filter.'])
  421. end
  422. try
  423. if isfield(filter(i).Subfilter, 'Position')
  424. printAttributeArray(fid, {'x','y','width','height'}, filter(i).Subfilter, 'Position');
  425. end
  426. printAttributeString(fid, 'result', filter(i).Subfilter, 'Result');
  427. % Add result string to the list in order to check the in
  428. % strings.
  429. resultStrings{length(resultStrings) + 1} = filter(i).Subfilter.Result;
  430. % The strmatch below is a very inefficient search (Matlab limitation)
  431. if ~isempty(strmatch(filter(i).Subfilter.Result, predefinedSources))
  432. error('Usage of a predefined filter source as filter result string is not allowed.');
  433. end
  434. switch (filter(i).Subfilter.Type)
  435. case 'feGaussianBlur'
  436. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings);
  437. printAttributeDouble(fid, 'stdDeviation', filter(i).Subfilter, 'Deviation');
  438. fprintf(fid,' />\n');
  439. case 'feImage'
  440. printAttributeString(fid, 'xlink:href', filter(i).Subfilter, 'File');
  441. printAttributeString(fid, 'preserveAspectRatio', filter(i).Subfilter, 'AspectRatio', 'xMidYMid meet');
  442. fprintf(fid,' />\n');
  443. case 'feComposite'
  444. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings);
  445. printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings);
  446. printAttributeList(fid, 'operator', filter(i).Subfilter, 'Operator', {'over','in','out','atop','xor','arithmetic'}, 'over'); % 'over' | 'in' | 'out' | 'atop' | 'xor' | 'arithmetic'
  447. if isfield(filter(i).Subfilter, 'Operator') && strcmp(filter(i).Subfilter.Operator, 'arithmetic')
  448. printAttributeArray(fid, {'k1','k2','k3','k4'}, filter(i).Subfilter, 'k');
  449. end
  450. fprintf(fid,' />\n');
  451. case 'feSpecularLighting'
  452. printAttributeDouble(fid, 'specularConstant', filter(i).Subfilter, 'SpecularConstant');
  453. printAttributeDouble(fid, 'specularExponent', filter(i).Subfilter, 'SpecularExponent');
  454. printAttributeDouble(fid, 'surfaceScale', filter(i).Subfilter, 'SurfaceScale');
  455. fprintf(fid,' style="lighting-color:white"');
  456. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings);
  457. fprintf(fid,' >\n');
  458. if isfield(filter(i).Subfilter, 'LightType')
  459. fprintf(fid,' <%s', filter(i).Subfilter.LightType);
  460. switch filter(i).Subfilter.LightType
  461. case 'feDistantLight'
  462. printAttributeDouble(fid, 'azimuth', filter(i).Subfilter, 'Azimuth');
  463. printAttributeDouble(fid, 'elevation', filter(i).Subfilter, 'Elevation');
  464. case 'fePointLight'
  465. printAttributeArray(fid, {'x','y','z'}, filter(i).Subfilter, 'Position');
  466. case 'feSpotLight'
  467. printAttributeArray(fid, {'x','y','z'}, filter(i).Subfilter, 'Position');
  468. printAttributeArray(fid, {'pointsAtX','pointsAtY','pointsAtZ'}, filter(i).Subfilter, 'PositionsAt');
  469. printAttributeDouble(fid, 'specularExponent', filter(i).Subfilter, 'LightSpecularExponent');
  470. printAttributeDouble(fid, 'limitingConeAngle', filter(i).Subfilter, 'LimitingConeAngle');
  471. otherwise, error(['Unknown light type ''' filter(i).Subfilter.LightType ''.']);
  472. end
  473. fprintf(fid,' />\n');
  474. else
  475. error('Missing field ''LightType''.');
  476. end
  477. fprintf(fid,'</%s>\n',filter(i).Subfilter.Type);
  478. case 'feOffset'
  479. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings);
  480. printAttributeArray(fid, {'dx','dy'}, filter(i).Subfilter, 'Offset');
  481. fprintf(fid,' />\n');
  482. case 'feBlend'
  483. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings);
  484. printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings);
  485. printAttributeList(fid, 'mode', filter(i).Subfilter, 'Mode', {'normal','multiply','screen','darken','lighten'}, 'normal'); % 'normal' | 'multiply' | 'screen' | 'darken' | 'lighten'
  486. fprintf(fid,' />\n');
  487. case 'feTurbulence'
  488. printAttributeDouble(fid, 'baseFrequency', filter(i).Subfilter, 'BaseFrequency');
  489. printAttributeDouble(fid, 'numOctaves', filter(i).Subfilter, 'NumOctaves');
  490. printAttributeDouble(fid, 'seed', filter(i).Subfilter, 'Seed');
  491. printAttributeList(fid, 'stitchTiles', filter(i).Subfilter, 'StitchTiles', {'stitch','noStitch'}, 'noStitch'); % stitch | noStitch
  492. printAttributeList(fid, 'type', filter(i).Subfilter, 'TurbulenceType', {'fractalNoise','turbulence'}, 'turbulence'); % 'fractalNoise' | 'turbulence'
  493. fprintf(fid,' />\n');
  494. case 'feColorMatrix'
  495. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings);
  496. printAttributeList(fid, 'type', filter(i).Subfilter, 'ColorType', {'matrix','saturate','hueRotate','luminanceToAlpha'}); % 'matrix' | 'saturate' | 'hueRotate' | 'luminanceToAlpha'
  497. if isfield(filter(i).Subfilter, 'ColorType') && strcmp(filter(i).Subfilter.ColorType, 'matrix')
  498. if isfield(filter(i).Subfilter, 'Matrix') && (lenght(filter(i).Subfilter.Matrix) == 20)
  499. fprintf(fid,' values="');
  500. fprintf(fid,' %0.3f', filter(i).Subfilter.Matrix);
  501. fprintf(fid,'"');
  502. else
  503. error('Field ''Matrix'' is missing or not a 5x4 matrix.');
  504. end
  505. end
  506. if isfield(filter(i).Subfilter, 'ColorType') && (strcmp(filter(i).Subfilter.ColorType, 'saturate') || strcmp(filter(i).Subfilter.ColorType, 'hueRotate'))
  507. printAttributeDouble(fid, 'values', filter(i).Subfilter, 'Matrix');
  508. end
  509. fprintf(fid,' />\n');
  510. case 'feFlood'
  511. printAttributeColor(fid, 'flood-color', filter(i).Subfilter, 'Color');
  512. printAttributeDouble(fid, 'flood-opacity', filter(i).Subfilter, 'Opacity');
  513. fprintf(fid,' />\n');
  514. case 'feDisplacementMap'
  515. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings);
  516. printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings);
  517. printAttributeDouble(fid, 'scale', filter(i).Subfilter, 'Scale');
  518. printAttributeList(fid, 'xChannelSelector', filter(i).Subfilter, 'xChannel', {'R','G','B','A'}, 'A'); % 'R' | 'G' | 'B' | 'A'
  519. printAttributeList(fid, 'yChannelSelector', filter(i).Subfilter, 'yChannel', {'R','G','B','A'}, 'A'); % 'R' | 'G' | 'B' | 'A'
  520. fprintf(fid,' />\n');
  521. case 'feMerge'
  522. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings);
  523. printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings);
  524. printAttributeList(fid, 'mode', filter(i).Subfilter, 'Mode', {'normal','multiply','screen','darken','lighten'}); % 'normal' | 'multiply' | 'screen' | 'darken' | 'lighten'
  525. fprintf(fid,' />\n');
  526. case 'feMorphology'
  527. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings);
  528. printAttributeList(fid, 'operator', filter(i).Subfilter, 'Operator', {'erode','dilate'}); % 'erode' | 'dilate'
  529. printAttributeDouble(fid, 'radius', filter(i).Subfilter, 'Radius');
  530. fprintf(fid,' />\n');
  531. case 'feTile'
  532. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings);
  533. fprintf(fid,' />\n');
  534. case 'feDiffuseLighting'
  535. printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings);
  536. fprintf(fid,' style="lighting-color:white"');
  537. printAttributeDouble(fid, 'surfaceScale', filter(i).Subfilter, 'SurfaceScale');
  538. printAttributeDouble(fid, 'diffuseConstant', filter(i).Subfilter, 'DiffuseConstant');
  539. printAttributeDouble(fid, 'kernelUnitLength', filter(i).Subfilter, 'KernelUnitLength');
  540. fprintf(fid,' />\n');
  541. % case 'feConvolveMatrix'
  542. %
  543. % printAttributeDouble(fid, 'order', filter(i).Subfilter);
  544. % kernelMatrix
  545. % printAttributeDouble(fid, 'divisor', filter(i).Subfilter, 1.0);
  546. % printAttributeDouble(fid, 'bias', filter(i).Subfilter, 0);
  547. % targetX
  548. % targetY
  549. % printAttributeString(fid, 'edgeMode', filter(i).Subfilter, 'EdgeMode', 'duplicate');
  550. % fprintf(fid,' kernelUnitLength="1 1"');
  551. % printAttributeString(fid, 'preserveAlpha', filter(i).Subfilter, 'PreserveAlpha', 'true');
  552. % fprintf(fid,' />\n');
  553. case {'feComponentTransfer','feConvolveMatrix'}
  554. error('Filter not yet implemented.');
  555. otherwise
  556. error(['Unknown filter ''' filter(i).Subfilter.Type '''.']);
  557. end
  558. catch
  559. error([lasterr ' Error is caused by filter type ''' filter(i).Subfilter.Type '''.']);
  560. end
  561. end
  562. fprintf(fid,' </filter>\n');
  563. fprintf(fid,'</defs>\n');
  564. end
  565. end
  566. end
  567. function printAttributeArray(fid, names, svgstruct, svgfield)
  568. if isfield(svgstruct, svgfield)
  569. if isnumeric(svgstruct.(svgfield))
  570. if length(svgstruct.(svgfield)) ~= length(names)
  571. error(['Length mismatch for field ''' svgfield '''.'])
  572. end
  573. for i = 1:length(names)
  574. fprintf(fid,' %s="%0.3f"', names{i}, svgstruct.(svgfield)(i));
  575. end
  576. else
  577. error(['Field ''' svgfield ''' must be numeric.']);
  578. end
  579. else
  580. if nargin < 5
  581. error(['Missing field ''' svgfield '''.'])
  582. else
  583. for i = 1:length(names)
  584. fprintf(fid,' %s="%0.3f"', names{i}, default(i));
  585. end
  586. end
  587. end
  588. function printAttributeDouble(fid, name, svgstruct, svgfield, default)
  589. if isfield(svgstruct, svgfield)
  590. if isnumeric(svgstruct.(svgfield))
  591. fprintf(fid,' %s="%0.3f"', name, svgstruct.(svgfield));
  592. else
  593. error(['Field ''' svgfield ''' must be numeric.']);
  594. end
  595. else
  596. if nargin < 5
  597. error(['Missing field ''' svgfield '''.'])
  598. else
  599. fprintf(fid,' %s="%0.3f"', name, default);
  600. end
  601. end
  602. function printAttributeIn(fid, name, svgstruct, svgfield, default, resultStrings)
  603. if isfield(svgstruct, svgfield)
  604. if ischar(svgstruct.(svgfield))
  605. % The strmatch below is a very inefficient search (Matlab limitation)
  606. if isempty(strmatch(svgstruct.(svgfield), resultStrings))
  607. error(['The source string ''' svgstruct.(svgfield) ''' was never a result string of a previous filter. Check for correct spelling.']);
  608. else
  609. fprintf(fid,' %s="%s"', name, svgstruct.(svgfield));
  610. end
  611. else
  612. error(['Field ''' svgfield ''' must be a string.']);
  613. end
  614. else
  615. if nargin < 5
  616. error(['Missing field ''' svgfield '''.'])
  617. else
  618. fprintf(fid,' %s="%s"', name, default);
  619. end
  620. end
  621. function printAttributeString(fid, name, svgstruct, svgfield, default)
  622. if isfield(svgstruct, svgfield)
  623. if ischar(svgstruct.(svgfield))
  624. fprintf(fid,' %s="%s"', name, svgstruct.(svgfield));
  625. else
  626. error(['Field ''' svgfield ''' must be a string.']);
  627. end
  628. else
  629. if nargin < 5
  630. error(['Missing field ''' svgfield '''.'])
  631. else
  632. fprintf(fid,' %s="%s"', name, default);
  633. end
  634. end
  635. function printAttributeList(fid, name, svgstruct, svgfield, list, default)
  636. if isfield(svgstruct, svgfield)
  637. if ischar(svgstruct.(svgfield))
  638. if isempty(strmatch(svgstruct.(svgfield), list))
  639. listString = strcat(list, ''' | ''');
  640. listString = [listString{:}];
  641. error(['Illegal string identifier ''' svgstruct.(svgfield) '''. Must be one out of the list: ''' listString(1:end-4) '.']);
  642. else
  643. fprintf(fid,' %s="%s"', name, svgstruct.(svgfield));
  644. end
  645. else
  646. error(['Field ''' svgfield ''' must be a string.']);
  647. end
  648. else
  649. if nargin < 6
  650. error(['Missing field ''' svgfield '''.'])
  651. else
  652. fprintf(fid,' %s="%s"', name, default);
  653. end
  654. end
  655. function printAttributeColor(fid, name, svgstruct, svgfield, default)
  656. if isfield(svgstruct, svgfield)
  657. if isnumeric(svgstruct.(svgfield))
  658. if length(svgstruct.(svgfield)) ~= 3
  659. error(['Color must be a 1x3 vector for field ''' svgfield '''.'])
  660. else
  661. fprintf(fid,' %s="%s"', name, searchcolor(gca, svgstruct.(svgfield)));
  662. end
  663. else
  664. error(['Field ''' svgfield ''' must be a 1x3 vector.']);
  665. end
  666. else
  667. if nargin < 5
  668. error(['Missing field ''' svgfield '''.'])
  669. else
  670. fprintf(fid,' %s="%s"', name, default);
  671. end
  672. end
  673. function frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, tick, index, edge_neighbours, c, valid_ticks, ticklength, tick_ratio, lim, drawBorder)
  674. for k = 1:length(index)
  675. x_tick_end1 = interp1([0 1],[x(index(k)) x(edge_neighbours(index(k),c(1)))],ticklength*tick_ratio(c(3)),'linear','extrap');
  676. y_tick_end1 = interp1([0 1],[y(index(k)) y(edge_neighbours(index(k),c(1)))],ticklength*tick_ratio(c(3)),'linear','extrap');
  677. x_tick_end2 = interp1([0 1],[x(edge_neighbours(index(k),c(2))) x(edge_neighbours(edge_neighbours(index(k),c(2)),c(1)))],ticklength*tick_ratio(c(3)),'linear','extrap');
  678. y_tick_end2 = interp1([0 1],[y(edge_neighbours(index(k),c(2))) y(edge_neighbours(edge_neighbours(index(k),c(2)),c(1)))],ticklength*tick_ratio(c(3)),'linear','extrap');
  679. xg_line_start = interp1(lim,[x(index(k)) x(edge_neighbours(index(k),c(2)))],tick);
  680. yg_line_start = interp1(lim,[y(index(k)) y(edge_neighbours(index(k),c(2)))],tick);
  681. xg_line_end = interp1(lim,[x_tick_end1 x_tick_end2],tick);
  682. yg_line_end = interp1(lim,[y_tick_end1 y_tick_end2],tick);
  683. for i = valid_ticks
  684. line2svg(fid,grouplabel,axpos,[xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)],scolorname,'-',linewidth)
  685. end
  686. if drawBorder
  687. line2svg(fid,grouplabel,axpos,[x(index(k)) x(edge_neighbours(index(k),c(2)))],[y(index(k)) y(edge_neighbours(index(k),c(2)))],scolorname,'-',linewidth)
  688. end
  689. end
  690. function gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlim, axtick, axindex_inner, corners, c)
  691. xg_line_start = interp1([axlim(1) axlim(2)],[x(corners(c(1))) x(corners(c(2)))], axtick);
  692. yg_line_start = interp1([axlim(1) axlim(2)],[y(corners(c(1))) y(corners(c(2)))], axtick);
  693. xg_line_end = interp1([axlim(1) axlim(2)],[x(corners(c(3))) x(corners(c(4)))], axtick);
  694. yg_line_end = interp1([axlim(1) axlim(2)],[y(corners(c(3))) y(corners(c(4)))], axtick);
  695. for i = axindex_inner
  696. line2svg(fid, grouplabel, axpos, [xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)], scolorname, gridlinestyle, linewidth)
  697. end
  698. function minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlim, minor_axtick, corners, c)
  699. xg_line_start = interp1([axlim(1) axlim(2)],[x(corners(c(1))) x(corners(c(2)))], minor_axtick);
  700. yg_line_start = interp1([axlim(1) axlim(2)],[y(corners(c(1))) y(corners(c(2)))], minor_axtick);
  701. xg_line_end = interp1([axlim(1) axlim(2)],[x(corners(c(3))) x(corners(c(4)))], minor_axtick);
  702. yg_line_end = interp1([axlim(1) axlim(2)],[y(corners(c(3))) y(corners(c(4)))], minor_axtick);
  703. for i = 1:length(xg_line_start)
  704. line2svg(fid, grouplabel, axpos, [xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)], scolorname, minor_gridlinestyle, linewidth)
  705. end
  706. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SUBFUNCTIONS %%%%%
  707. % Create axis frame and insert all children of this axis frame
  708. function group=axes2svg(fid,id,ax,group,paperpos)
  709. global colorname
  710. global PLOT2SVG_globals
  711. originalAxesUnits=get(ax,'Units');
  712. set(ax,'Units','normalized');
  713. axpos=get(ax,'Position');
  714. faces = [1 2 4 3; 2 4 8 6; 3 4 8 7; 1 2 6 5; 1 5 7 3; 5 6 8 7];
  715. % x-y ; y-z ; x-z ; y-z ; x-z ; x-y
  716. corners(:,:,1) = [1 1 2 3 4; 2 1 3 2 4];
  717. corners(:,:,2) = [2 2 4 6 8; 3 2 6 4 8];
  718. corners(:,:,3) = [1 3 4 7 8; 3 3 7 4 8];
  719. corners(:,:,4) = [1 1 2 5 6; 3 1 5 2 6];
  720. corners(:,:,5) = [2 1 3 5 7; 3 1 5 3 7];
  721. corners(:,:,6) = [1 5 6 7 8; 2 5 7 6 8];
  722. edge_neighbours = [2 3 5; 1 4 6; 4 1 7; 3 2 8; 6 7 1; 5 8 2; 8 5 3; 7 6 4];
  723. edge_opposite = [8 7 6 5 4 3 2 1];
  724. nomx = [0 1 0 1 0 1 0 1];
  725. nomy = [0 0 1 1 0 0 1 1];
  726. nomz = [0 0 0 0 1 1 1 1];
  727. [projection,edges] = get_projection(ax,id);
  728. x = (edges(1,:)*axpos(3)+axpos(1))*paperpos(3);
  729. y = (1-(edges(2,:)*axpos(4)+axpos(2)))*paperpos(4);
  730. % Depth Sort of view box edges
  731. [edge_z,edge_index]=sort(edges(3,:));
  732. most_back_edge_index = edge_index(1);
  733. % Back faces are plot box faces that are behind the plot (as seen by the
  734. % view point)
  735. back_faces = find(any(faces == most_back_edge_index,2));
  736. front_faces = find(all(faces ~= most_back_edge_index,2));
  737. groupax=group;
  738. axlimx=get(ax,'XLim');
  739. axlimy=get(ax,'YLim');
  740. axlimz=get(ax,'ZLim');
  741. axlimxori=axlimx;
  742. axlimyori=axlimy;
  743. axlimzori=axlimz;
  744. if strcmp(get(ax,'XScale'),'log')
  745. axlimx=log10(axlimx);
  746. axlimx(find(isinf(axlimx)))=0;
  747. end
  748. if strcmp(get(ax,'YScale'),'log')
  749. axlimy=log10(axlimy);
  750. axlimy(find(isinf(axlimy)))=0;
  751. end
  752. if strcmp(get(ax,'ZScale'),'log')
  753. axlimz=log10(axlimz);
  754. axlimz(find(isinf(axlimz)))=0;
  755. end
  756. if strcmp(get(ax,'XDir'),'reverse')
  757. axlimx = fliplr(axlimx);
  758. end
  759. if strcmp(get(ax,'YDir'),'reverse')
  760. axlimy = fliplr(axlimy);
  761. end
  762. if strcmp(get(ax,'ZDir'),'reverse')
  763. axlimz = fliplr(axlimz);
  764. end
  765. axlimori = [axlimxori(1) axlimyori(1) axlimzori(1) axlimxori(2)-axlimxori(1) axlimyori(2)-axlimyori(1) axlimzori(2)-axlimzori(1)];
  766. fprintf(fid,' <g id ="%s">\n', createId);
  767. axIdString = createId;
  768. boundingBoxAxes = [min(x) min(y) max(x)-min(x) max(y)-min(y)];
  769. fprintf(fid,' <clipPath id="%s">\n',axIdString);
  770. fprintf(fid,' <rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f"/>\n',...
  771. boundingBoxAxes(1), boundingBoxAxes(2), boundingBoxAxes(3), boundingBoxAxes(4));
  772. fprintf(fid,' </clipPath>\n');
  773. if strcmp(get(ax,'Visible'),'on')
  774. group=group+1;
  775. grouplabel=group;
  776. axxtick=get(ax,'XTick');
  777. axytick=get(ax,'YTick');
  778. axztick=get(ax,'ZTick');
  779. axlabelx=get(ax,'XTickLabel');
  780. axlabely=get(ax,'YTickLabel');
  781. axlabelz=get(ax,'ZTickLabel');
  782. % Workaround for Octave
  783. if PLOT2SVG_globals.octave
  784. if isempty(axlabelx)
  785. if strcmp(get(ax,'XScale'),'log')
  786. axlabelx = num2str(log10(axxtick)');
  787. else
  788. axlabelx = num2str(axxtick');
  789. end
  790. end
  791. if isempty(axlabely)
  792. if strcmp(get(ax,'YScale'),'log')
  793. axlabely = num2str(log10(axytick)');
  794. else
  795. axlabely = num2str(axytick');
  796. end
  797. end
  798. if isempty(axlabelz)
  799. if strcmp(get(ax,'ZScale'),'log')
  800. axlabelz = num2str(log10(axztick)');
  801. else
  802. axlabelz = num2str(axztick');
  803. end
  804. end
  805. if projection.xyplane
  806. axlabelz = [];
  807. end
  808. end
  809. gridlinestyle=get(ax,'GridLineStyle');
  810. minor_gridlinestyle=get(ax,'MinorGridLineStyle');
  811. try % Octave does not have 'TickLength' yet. --Jakob Malm
  812. both_ticklength = get(ax,'TickLength');
  813. catch
  814. both_ticklength = [ 0.01 0.025 ];
  815. end
  816. gridBehind = true; % Default setting
  817. try
  818. if strcmp(get(ax, 'Layer'), 'top') && projection.xyplane
  819. gridBehind = false;
  820. end
  821. catch
  822. gridBehind = true;
  823. end
  824. if projection.xyplane
  825. ticklength = both_ticklength(1);
  826. xy_ratio = axpos(3)*paperpos(3)/ (axpos(4)*paperpos(4));
  827. if xy_ratio < 1
  828. tick_ratio = [1 1/xy_ratio 1];
  829. else
  830. tick_ratio = [xy_ratio 1 1];
  831. end
  832. if strcmp(get(ax,'TickDir'),'out')
  833. label_distance = -(0.02 + ticklength);
  834. else
  835. label_distance = -0.02;
  836. end
  837. else
  838. ticklength = both_ticklength(2);
  839. label_distance = -2*abs(ticklength);
  840. tick_ratio = [1 1 1];
  841. end
  842. linewidth = get(ax,'LineWidth');
  843. axxindex=find((axxtick >= axlimori(1)) & (axxtick <= (axlimori(1)+axlimori(4))));
  844. axyindex=find((axytick >= axlimori(2)) & (axytick <= (axlimori(2)+axlimori(5))));
  845. axzindex=find((axztick >= axlimori(3)) & (axztick <= (axlimori(3)+axlimori(6))));
  846. % remove sticks outside of the axes (-1 of legends)
  847. axxtick=axxtick(axxindex);
  848. axytick=axytick(axyindex);
  849. axztick=axztick(axzindex);
  850. if length(axxtick) > 1
  851. minor_lin_sticks = (0.2:0.2:0.8)*(axxtick(2)-axxtick(1));
  852. minor_axxtick = [];
  853. for stick = [2*axxtick(1)-axxtick(2) axxtick]
  854. minor_axxtick = [minor_axxtick minor_lin_sticks + stick];
  855. end
  856. minor_axxtick = minor_axxtick(find(minor_axxtick > min(axlimx) & minor_axxtick < max(axlimx)));
  857. else
  858. minor_axxtick = [];
  859. end
  860. if length(axytick) > 1
  861. minor_lin_sticks = (0.2:0.2:0.8)*(axytick(2)-axytick(1));
  862. minor_axytick = [];
  863. for stick = [2*axytick(1)-axytick(2) axytick]
  864. minor_axytick = [minor_axytick minor_lin_sticks + stick];
  865. end
  866. minor_axytick = minor_axytick(find(minor_axytick > min(axlimy) & minor_axytick < max(axlimy)));
  867. else
  868. minor_axytick = [];
  869. end
  870. if length(axztick) > 1
  871. minor_lin_sticks = (0.2:0.2:0.8)*(axztick(2)-axztick(1));
  872. minor_axztick = [];
  873. for stick = [2*axztick(1)-axztick(2) axztick]
  874. minor_axztick = [minor_axztick minor_lin_sticks + stick];
  875. end
  876. minor_axztick = minor_axztick(find(minor_axztick > min(axlimz) & minor_axztick < max(axlimz)));
  877. else
  878. minor_axztick = [];
  879. end
  880. if strcmp(get(ax,'Box'),'on')
  881. axxindex_inner = find((axxtick > axlimori(1)) & (axxtick < (axlimori(1)+axlimori(4))));
  882. axyindex_inner = find((axytick > axlimori(2)) & (axytick < (axlimori(2)+axlimori(5))));
  883. axzindex_inner = find((axztick > axlimori(3)) & (axztick < (axlimori(3)+axlimori(6))));
  884. else
  885. axxindex_inner = find((axxtick >= axlimori(1)) & (axxtick <= (axlimori(1)+axlimori(4))));
  886. axyindex_inner = find((axytick >= axlimori(2)) & (axytick <= (axlimori(2)+axlimori(5))));
  887. axzindex_inner = find((axztick >= axlimori(3)) & (axztick <= (axlimori(3)+axlimori(6))));
  888. end
  889. minor_log_sticks = log10(0.2:0.1:0.9);
  890. if strcmp(get(ax,'TickDir'),'out')
  891. ticklength=-ticklength;
  892. valid_xsticks = 1:length(axxindex);
  893. valid_ysticks = 1:length(axyindex);
  894. valid_zsticks = 1:length(axzindex);
  895. else
  896. valid_xsticks = axxindex_inner;
  897. valid_ysticks = axyindex_inner;
  898. valid_zsticks = axzindex_inner;
  899. end
  900. if strcmp(get(ax,'XScale'),'log')
  901. axxtick = log10(get(ax,'XTick'));
  902. minor_axxtick = [];
  903. if ~isempty(axxtick)
  904. all_axxtick = axxtick(1):1:axxtick(end);
  905. for stick = all_axxtick
  906. minor_axxtick = [minor_axxtick minor_log_sticks + stick];
  907. end
  908. end
  909. minor_axxtick = minor_axxtick(find(minor_axxtick > min(axlimx) & minor_axxtick < max(axlimx)));
  910. end
  911. if strcmp(get(ax,'YScale'),'log')
  912. axytick=log10(get(ax,'YTick'));
  913. minor_axytick = [];
  914. if ~isempty(axytick)
  915. all_axytick = axytick(1):1:axytick(end);
  916. for stick = all_axytick
  917. minor_axytick = [minor_axytick minor_log_sticks + stick];
  918. end
  919. end
  920. minor_axytick = minor_axytick(find(minor_axytick > min(axlimy) & minor_axytick < max(axlimy)));
  921. end
  922. if strcmp(get(ax,'ZScale'),'log')
  923. axztick=log10(get(ax,'ZTick'));
  924. minor_axztick = [];
  925. if ~isempty(axztick)
  926. all_axztick = axztick(1):1:axztick(end);
  927. for stick = all_axztick
  928. minor_axztick = [minor_axztick minor_log_sticks + stick];
  929. end
  930. end
  931. minor_axztick = minor_axztick(find(minor_axztick > min(axlimz) & minor_axztick < max(axlimz)));
  932. end
  933. % Draw back faces
  934. linewidth=get(ax,'LineWidth');
  935. if ~strcmp(get(ax,'Color'),'none')
  936. background_color = searchcolor(id,get(ax,'Color'));
  937. background_opacity = 1;
  938. else
  939. background_color = '#000000';
  940. background_opacity = 0;
  941. end
  942. for p=1:size(back_faces)
  943. patch2svg(fid, group, axpos, x(faces(back_faces(p),:)), y(faces(back_faces(p),:)), background_color, '-', linewidth, 'none', background_opacity, 1.0, true)
  944. end
  945. for pindex = 1:size(back_faces)
  946. p = back_faces(pindex);
  947. for k = 1:size(corners,1)
  948. selectedCorners = squeeze(corners(k,:,p));
  949. switch corners(k,1,p)
  950. case 1 % x
  951. % Draw x-grid
  952. scolorname = searchcolor(id,get(ax,'XColor'));
  953. if strcmp(get(ax,'XGrid'),'on') && gridBehind
  954. if axlimx(1)~=axlimx(2)
  955. gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimx, axxtick, axxindex_inner, selectedCorners, [2 3 4 5])
  956. if strcmp(get(ax,'XTickMode'),'auto') && strcmp(get(ax,'XMinorGrid'),'on') && ~isempty(minor_axxtick)
  957. minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimx, minor_axxtick, selectedCorners, [2 3 4 5])
  958. end
  959. end
  960. end
  961. if projection.xyplane == false
  962. if strcmp(get(ax,'Box'),'on')
  963. line2svg(fid,grouplabel,axpos,[x(corners(k,2,p)) x(corners(k,3,p))],[y(corners(k,2,p)) y(corners(k,3,p))],scolorname,'-',linewidth);
  964. line2svg(fid,grouplabel,axpos,[x(corners(k,4,p)) x(corners(k,5,p))],[y(corners(k,4,p)) y(corners(k,5,p))],scolorname,'-',linewidth);
  965. else
  966. if strcmp(get(ax,'XGrid'),'on')
  967. line2svg(fid,grouplabel,axpos,[x(corners(k,2,p)) x(corners(k,3,p))],[y(corners(k,2,p)) y(corners(k,3,p))],scolorname,gridlinestyle,linewidth);
  968. line2svg(fid,grouplabel,axpos,[x(corners(k,4,p)) x(corners(k,5,p))],[y(corners(k,4,p)) y(corners(k,5,p))],scolorname,gridlinestyle,linewidth);
  969. end
  970. end
  971. end
  972. case 2 % y
  973. % Draw y-grid
  974. scolorname = searchcolor(id,get(ax,'YColor'));