/code/plot2svg.m

https://github.com/hananel/piggottDesignCode · Objective C · 3079 lines · 3032 code · 47 blank · 0 comment · 588 complexity · d8b3bad0a49ffca9f1c0f150d16951b8 MD5 · raw 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'));
  975. if strcmp(get(ax,'YGrid'),'on') && gridBehind
  976. if axlimy(1)~=axlimy(2)
  977. gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimy, axytick, axyindex_inner, selectedCorners, [2 3 4 5])
  978. if strcmp(get(ax,'YTickMode'),'auto') && strcmp(get(ax,'YMinorGrid'),'on') && ~isempty(minor_axytick)
  979. minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimy, minor_axytick, selectedCorners, [2 3 4 5])
  980. end
  981. end
  982. end
  983. if projection.xyplane == false
  984. if strcmp(get(ax,'Box'),'on')
  985. 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);
  986. 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);
  987. else
  988. if strcmp(get(ax,'YGrid'),'on')
  989. 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);
  990. 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);
  991. end
  992. end
  993. end
  994. case 3 % z
  995. % Draw z-grid
  996. scolorname = searchcolor(id,get(ax,'ZColor'));
  997. if strcmp(get(ax,'ZGrid'),'on') && gridBehind
  998. if axlimz(1)~=axlimz(2)
  999. gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimz, axztick, axzindex_inner, selectedCorners, [2 3 4 5])
  1000. if strcmp(get(ax,'ZTickMode'),'auto') && strcmp(get(ax,'ZMinorGrid'),'on') && ~isempty(minor_axztick)
  1001. minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimz, minor_axztick, selectedCorners, [2 3 4 5])
  1002. end
  1003. end
  1004. end
  1005. if projection.xyplane == false
  1006. if strcmp(get(ax,'Box'),'on')
  1007. 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);
  1008. 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);
  1009. else
  1010. if strcmp(get(ax,'ZGrid'),'on')
  1011. 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);
  1012. 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);
  1013. end
  1014. end
  1015. end
  1016. end
  1017. end
  1018. end
  1019. end
  1020. fprintf(fid,' <g>\n');
  1021. axchild=get(ax,'Children');
  1022. group = axchild2svg(fid,id,axIdString,ax,group,paperpos,axchild,axpos,groupax,projection,boundingBoxAxes);
  1023. fprintf(fid,' </g>\n');
  1024. if strcmp(get(ax,'Visible'),'on')
  1025. fprintf(fid,' <g>\n');
  1026. % Search axis for labeling
  1027. if projection.xyplane
  1028. [x_axis_point_value, x_axis_point_index_top] = min(y);
  1029. [x_axis_point_value, x_axis_point_index_bottom] = max(y);
  1030. if strcmp(get(ax,'Box'),'on')
  1031. if strcmp(get(ax,'XAxisLocation'),'top')
  1032. x_axis_point_index = [x_axis_point_index_top x_axis_point_index_bottom];
  1033. else
  1034. x_axis_point_index = [x_axis_point_index_bottom x_axis_point_index_top];
  1035. end
  1036. else
  1037. if strcmp(get(ax,'XAxisLocation'),'top')
  1038. x_axis_point_index = x_axis_point_index_top;
  1039. else
  1040. x_axis_point_index = x_axis_point_index_bottom;
  1041. end
  1042. end
  1043. [y_axis_point_value, y_axis_point_index_left] = min(x);
  1044. [y_axis_point_value, y_axis_point_index_right] = max(x);
  1045. if strcmp(get(ax,'Box'),'on')
  1046. if strcmp(get(ax,'YAxisLocation'),'right')
  1047. y_axis_point_index = [y_axis_point_index_right y_axis_point_index_left];
  1048. else
  1049. y_axis_point_index = [y_axis_point_index_left y_axis_point_index_right];
  1050. end
  1051. else
  1052. if strcmp(get(ax,'YAxisLocation'),'right')
  1053. y_axis_point_index = y_axis_point_index_right;
  1054. else
  1055. y_axis_point_index = y_axis_point_index_left;
  1056. end
  1057. end
  1058. [z_axis_point_value, z_axis_point_index] = min(x);
  1059. else
  1060. [x_axis_point_value, x_axis_point_index] = max(y);
  1061. [y_axis_value, y_axis_point_index] = max(y);
  1062. [z_axis_point_value, z_axis_point_index] = min(x);
  1063. end
  1064. % Draw grid
  1065. for pindex = 1:size(front_faces)
  1066. p = front_faces(pindex);
  1067. for k = 1:size(corners,1)
  1068. selectedCorners = squeeze(corners(k,:,p));
  1069. switch corners(k,1,p)
  1070. case 1 % x
  1071. % Draw x-grid
  1072. scolorname = searchcolor(id,get(ax,'XColor'));
  1073. if strcmp(get(ax,'XGrid'),'on') && gridBehind == false
  1074. if axlimx(1)~=axlimx(2)
  1075. gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimx, axxtick, axxindex_inner, selectedCorners, [2 3 4 5])
  1076. if strcmp(get(ax,'XTickMode'),'auto') && strcmp(get(ax,'XMinorGrid'),'on') && ~isempty(minor_axxtick)
  1077. minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimx, minor_axxtick, selectedCorners, [2 3 4 5])
  1078. end
  1079. end
  1080. end
  1081. case 2 % y
  1082. % Draw y-grid
  1083. scolorname = searchcolor(id,get(ax,'YColor'));
  1084. if strcmp(get(ax,'YGrid'),'on') && gridBehind == false
  1085. if axlimy(1)~=axlimy(2)
  1086. gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimy, axytick, axyindex_inner, selectedCorners, [2 3 4 5])
  1087. if strcmp(get(ax,'YTickMode'),'auto') && strcmp(get(ax,'YMinorGrid'),'on') && ~isempty(minor_axytick)
  1088. minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimy, minor_axytick, selectedCorners, [2 3 4 5])
  1089. end
  1090. end
  1091. end
  1092. case 3 % z
  1093. % Draw z-grid
  1094. scolorname = searchcolor(id,get(ax,'ZColor'));
  1095. if strcmp(get(ax,'ZGrid'),'on') && gridBehind == false
  1096. if axlimz(1)~=axlimz(2)
  1097. gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimz, axztick, axzindex_inner, selectedCorners, [2 3 4 5])
  1098. if strcmp(get(ax,'ZTickMode'),'auto') && strcmp(get(ax,'ZMinorGrid'),'on') && ~isempty(minor_axztick)
  1099. minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimz, minor_axztick, selectedCorners, [2 3 4 5])
  1100. end
  1101. end
  1102. end
  1103. end
  1104. end
  1105. end
  1106. scolorname=searchcolor(id,get(ax,'XColor'));
  1107. % Draw 'box' of x-axis
  1108. if projection.xyplane == false
  1109. if strcmp(get(ax,'Box'),'on')
  1110. edge_line_index = [edge_opposite(most_back_edge_index) edge_neighbours(edge_opposite(most_back_edge_index),1)];
  1111. line2svg(fid,grouplabel,axpos,x(edge_line_index),y(edge_line_index),scolorname,'-',linewidth)
  1112. end
  1113. end
  1114. % Draw x-tick labels
  1115. if (strcmp(get(ax,'XTickLabelMode'),'auto') && strcmp(get(ax,'XScale'),'log'))
  1116. exponent = 1;
  1117. else
  1118. exponent = 0;
  1119. end
  1120. % Draw x-tick marks
  1121. if (ticklength(1) ~= 0)
  1122. if axlimx(1)~=axlimx(2)
  1123. if (nomx(x_axis_point_index(1)))
  1124. lim = [axlimx(2) axlimx(1)];
  1125. else
  1126. lim = [axlimx(1) axlimx(2)];
  1127. end
  1128. x_label_end1 = interp1([0 1],[x(x_axis_point_index(1)) x(edge_neighbours(x_axis_point_index(1),2))],label_distance,'linear','extrap');
  1129. y_label_end1 = interp1([0 1],[y(x_axis_point_index(1)) y(edge_neighbours(x_axis_point_index(1),2))],label_distance,'linear','extrap');
  1130. x_label_end2 = interp1([0 1],[x(edge_neighbours(x_axis_point_index(1),1)) x(edge_neighbours(edge_neighbours(x_axis_point_index(1),1),2))],label_distance,'linear','extrap');
  1131. y_label_end2 = interp1([0 1],[y(edge_neighbours(x_axis_point_index(1),1)) y(edge_neighbours(edge_neighbours(x_axis_point_index(1),1),2))],label_distance,'linear','extrap');
  1132. xg_label_end = interp1(lim,[x_label_end1 x_label_end2],axxtick);
  1133. yg_label_end = interp1(lim,[y_label_end1 y_label_end2],axxtick);
  1134. frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ...
  1135. axxtick, x_axis_point_index, edge_neighbours, [2 1 1], ...
  1136. valid_xsticks, ticklength, tick_ratio, lim, true);
  1137. if strcmp(get(ax,'XTickMode'),'auto') && (strcmp(get(ax,'XMinorGrid'),'on') || strcmp(get(ax,'XScale'),'log')) && ~isempty(minor_axxtick)
  1138. frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ...
  1139. minor_axxtick, x_axis_point_index, edge_neighbours, [2 1 1], ...
  1140. 1:length(minor_axxtick), 0.5 * ticklength, tick_ratio, lim, false);
  1141. end
  1142. if ~isempty(axlabelx) && ~(iscell(axlabelx) && all(cellfun(@isempty,axlabelx)))
  1143. % Note: 3D plot do not support the property XAxisLocation
  1144. % setting 'top'.
  1145. [angle, align] = improvedXLabel(ax, 0, 'Center');
  1146. if strcmp(get(ax,'XAxisLocation'),'top') && (projection.xyplane == true)
  1147. for i = 1:length(axxindex)
  1148. label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelx(axxindex(i),:)),align,angle,'bottom',1,paperpos,scolorname,exponent);
  1149. end
  1150. else
  1151. for i = 1:length(axxindex)
  1152. label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelx(axxindex(i),:)),align,angle,'top',1,paperpos,scolorname,exponent);
  1153. end
  1154. end
  1155. end
  1156. end
  1157. end
  1158. scolorname=searchcolor(id,get(ax,'YColor'));
  1159. % Draw 'box' of y-axis
  1160. if projection.xyplane == false
  1161. if strcmp(get(ax,'Box'),'on')
  1162. edge_line_index = [edge_opposite(most_back_edge_index) edge_neighbours(edge_opposite(most_back_edge_index),2)];
  1163. line2svg(fid,grouplabel,axpos,x(edge_line_index),y(edge_line_index),scolorname,'-',linewidth)
  1164. end
  1165. end
  1166. % Draw y-tick labels
  1167. if (strcmp(get(ax,'YTickLabelMode'),'auto') && strcmp(get(ax,'YScale'),'log'))
  1168. exponent = 1;
  1169. else
  1170. exponent = 0;
  1171. end
  1172. % Draw y-tick marks
  1173. if (ticklength(1) ~= 0)
  1174. if axlimy(1)~=axlimy(2)
  1175. if (nomy(y_axis_point_index(1)))
  1176. lim = [axlimy(2) axlimy(1)];
  1177. else
  1178. lim = [axlimy(1) axlimy(2)];
  1179. end
  1180. x_label_end1 = interp1([0 1],[x(y_axis_point_index(1)) x(edge_neighbours(y_axis_point_index(1),1))],label_distance,'linear','extrap');
  1181. y_label_end1 = interp1([0 1],[y(y_axis_point_index(1)) y(edge_neighbours(y_axis_point_index(1),1))],label_distance,'linear','extrap');
  1182. x_label_end2 = interp1([0 1],[x(edge_neighbours(y_axis_point_index(1),2)) x(edge_neighbours(edge_neighbours(y_axis_point_index(1),2),1))],label_distance,'linear','extrap');
  1183. y_label_end2 = interp1([0 1],[y(edge_neighbours(y_axis_point_index(1),2)) y(edge_neighbours(edge_neighbours(y_axis_point_index(1),2),1))],label_distance,'linear','extrap');
  1184. xg_label_end = interp1(lim,[x_label_end1 x_label_end2],axytick);
  1185. yg_label_end = interp1(lim,[y_label_end1 y_label_end2],axytick);
  1186. frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ...
  1187. axytick, y_axis_point_index, edge_neighbours, [1 2 2], ...
  1188. valid_ysticks, ticklength, tick_ratio, lim, true);
  1189. if strcmp(get(ax,'YTickMode'),'auto') && (strcmp(get(ax,'YMinorGrid'),'on') || strcmp(get(ax,'YScale'),'log')) && ~isempty(minor_axytick)
  1190. frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ...
  1191. minor_axytick, y_axis_point_index, edge_neighbours, [1 2 2], ...
  1192. 1:length(minor_axytick), 0.5 * ticklength, tick_ratio, lim, false);
  1193. end
  1194. if ~isempty(axlabely) && ~(iscell(axlabely) && all(cellfun(@isempty,axlabely)))
  1195. % Note: 3D plot do not support the property YAxisLocation
  1196. % setting 'right'.
  1197. if (projection.xyplane == true)
  1198. if strcmp(get(ax,'YAxisLocation'),'right')
  1199. [angle, align] = improvedYLabel(ax, 0, 'Left');
  1200. for i = 1:length(axyindex)
  1201. label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely(axyindex(i),:)),align,angle,'middle',1,paperpos,scolorname,exponent);
  1202. end
  1203. else
  1204. [angle, align] = improvedYLabel(ax, 0, 'Right');
  1205. for i = 1:length(axyindex)
  1206. label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely(axyindex(i),:)),align,angle,'middle',1,paperpos,scolorname,exponent);
  1207. end
  1208. end
  1209. else
  1210. for i = 1:length(axyindex)
  1211. label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely(axyindex(i),:)),'Center',0,'top',1,paperpos,scolorname,exponent);
  1212. end
  1213. end
  1214. end
  1215. end
  1216. end
  1217. scolorname=searchcolor(id,get(ax,'ZColor'));
  1218. % Draw 'box' of z-axis
  1219. if projection.xyplane == false
  1220. if strcmp(get(ax,'Box'),'on')
  1221. edge_line_index = [edge_opposite(most_back_edge_index) edge_neighbours(edge_opposite(most_back_edge_index),3)];
  1222. line2svg(fid,grouplabel,axpos,x(edge_line_index),y(edge_line_index),scolorname,'-',linewidth)
  1223. end
  1224. end
  1225. if (strcmp(get(ax,'ZTickLabelMode'),'auto') && strcmp(get(ax,'ZScale'),'log'))
  1226. exponent = 1;
  1227. else
  1228. exponent = 0;
  1229. end
  1230. % Draw z-tick marks
  1231. if (ticklength(1) ~= 0)
  1232. if axlimz(1)~=axlimz(2)
  1233. if (nomz(z_axis_point_index(1)))
  1234. lim = [axlimz(2) axlimz(1)];
  1235. else
  1236. lim = [axlimz(1) axlimz(2)];
  1237. end
  1238. x_tick_end1 = interp1([0 1],[x(z_axis_point_index) x(edge_neighbours(z_axis_point_index,2))],ticklength*tick_ratio(3),'linear','extrap');
  1239. y_tick_end1 = interp1([0 1],[y(z_axis_point_index) y(edge_neighbours(z_axis_point_index,2))],ticklength*tick_ratio(3),'linear','extrap');
  1240. x_tick_end2 = interp1([0 1],[x(edge_neighbours(z_axis_point_index,3)) x(edge_neighbours(edge_neighbours(z_axis_point_index,3),2))],ticklength*tick_ratio(3),'linear','extrap');
  1241. y_tick_end2 = interp1([0 1],[y(edge_neighbours(z_axis_point_index,3)) y(edge_neighbours(edge_neighbours(z_axis_point_index,3),2))],ticklength*tick_ratio(3),'linear','extrap');
  1242. x_label_end1 = interp1([0 1],[x(z_axis_point_index) x(edge_neighbours(z_axis_point_index,2))],label_distance,'linear','extrap');
  1243. y_label_end1 = interp1([0 1],[y(z_axis_point_index) y(edge_neighbours(z_axis_point_index,2))],label_distance,'linear','extrap');
  1244. x_label_end2 = interp1([0 1],[x(edge_neighbours(z_axis_point_index,3)) x(edge_neighbours(edge_neighbours(z_axis_point_index,3),2))],label_distance,'linear','extrap');
  1245. y_label_end2 = interp1([0 1],[y(edge_neighbours(z_axis_point_index,3)) y(edge_neighbours(edge_neighbours(z_axis_point_index,3),2))],label_distance,'linear','extrap');
  1246. xg_line_start = interp1(lim,[x(z_axis_point_index) x(edge_neighbours(z_axis_point_index,3))],axztick);
  1247. yg_line_start = interp1(lim,[y(z_axis_point_index) y(edge_neighbours(z_axis_point_index,3))],axztick);
  1248. xg_line_end = interp1(lim,[x_tick_end1 x_tick_end2],axztick);
  1249. yg_line_end = interp1(lim,[y_tick_end1 y_tick_end2],axztick);
  1250. xg_label_end = interp1(lim,[x_label_end1 x_label_end2],axztick);
  1251. yg_label_end = interp1(lim,[y_label_end1 y_label_end2],axztick);
  1252. for i = valid_zsticks
  1253. line2svg(fid,grouplabel,axpos,[xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)],scolorname,'-',linewidth)
  1254. end
  1255. line2svg(fid,grouplabel,axpos,[x(z_axis_point_index) x(edge_neighbours(z_axis_point_index,3))],[y(z_axis_point_index) y(edge_neighbours(z_axis_point_index,3))],scolorname,'-',linewidth)
  1256. if ~isempty(axlabelz) && ~(iscell(axlabelz) && all(cellfun(@isempty,axlabelz)))
  1257. for i = 1:length(axzindex)
  1258. label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelz(axzindex(i),:)),'Right',0,'middle',1,paperpos,scolorname,exponent);
  1259. end
  1260. end
  1261. end
  1262. end
  1263. exponent2svg(fid,groupax,axpos,paperpos,ax)
  1264. fprintf(fid,' </g>\n');
  1265. end
  1266. fprintf(fid,' </g>\n');
  1267. set(ax,'Units',originalAxesUnits);
  1268. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1269. % take any axis children and create objects for them
  1270. function group=axchild2svg(fid,id,axIdString,ax,group,paperpos,axchild,axpos,groupax,projection,boundingBoxAxes)
  1271. global colorname
  1272. global PLOT2SVG_globals
  1273. for i=length(axchild):-1:1
  1274. if strcmp(get(axchild(i), 'Visible'), 'off')
  1275. % do nothing
  1276. elseif strcmp(get(axchild(i),'Type'),'line')
  1277. scolorname=searchcolor(id,get(axchild(i),'Color'));
  1278. linestyle=get(axchild(i),'LineStyle');
  1279. linewidth=get(axchild(i),'LineWidth');
  1280. marker=get(axchild(i),'Marker');
  1281. markeredgecolor=get(axchild(i),'MarkerEdgeColor');
  1282. if ischar(markeredgecolor)
  1283. switch markeredgecolor
  1284. case 'none',markeredgecolorname='none';
  1285. otherwise,markeredgecolorname=scolorname; % if markeredgecolorname is 'auto' or something else set the markeredgecolorname to the line color
  1286. end
  1287. else
  1288. markeredgecolorname=searchcolor(id,markeredgecolor);
  1289. end
  1290. markerfacecolor=get(axchild(i),'MarkerFaceColor');
  1291. if ischar(markerfacecolor)
  1292. switch markerfacecolor
  1293. case 'none',markerfacecolorname='none';
  1294. otherwise,markerfacecolorname=scolorname; % if markerfacecolorname is 'auto' or something else set the markerfacecolorname to the line color
  1295. end
  1296. else
  1297. markerfacecolorname=searchcolor(id,markerfacecolor);
  1298. end
  1299. markersize=get(axchild(i),'MarkerSize')/1.5;
  1300. linex = get(axchild(i),'XData');
  1301. linex = linex(:)'; % Octave stores the data in a column vector
  1302. if strcmp(get(ax,'XScale'),'log')
  1303. linex(find(linex<=0)) = NaN;
  1304. linex=log10(linex);
  1305. end
  1306. liney=get(axchild(i),'YData');
  1307. liney = liney(:)'; % Octave stores the data in a column vector
  1308. if strcmp(get(ax,'YScale'),'log')
  1309. liney(find(liney<=0)) = NaN;
  1310. liney=log10(liney);
  1311. end
  1312. linez=get(axchild(i),'ZData');
  1313. linez = linez(:)'; % Octave stores the data in a column vector
  1314. if isempty(linez)
  1315. linez = zeros(size(linex));
  1316. end
  1317. if strcmp(get(ax,'ZScale'),'log')
  1318. linez(find(linez<=0)) = NaN;
  1319. linez=log10(linez);
  1320. end
  1321. [x,y,z] = project(linex,liney,linez,projection);
  1322. x = (x*axpos(3)+axpos(1))*paperpos(3);
  1323. y = (1-(y*axpos(4)+axpos(2)))*paperpos(4);
  1324. markerOverlap = 0;
  1325. if ~strcmp(linestyle, 'none')
  1326. markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels'));
  1327. end
  1328. if ~strcmp(marker, 'none')
  1329. markerOverlap = max(markerOverlap, convertunit(markersize, 'points', 'pixels'));
  1330. end
  1331. boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap];
  1332. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement);
  1333. % put a line into a group with its markers
  1334. if strcmp(get(axchild(i),'Clipping'),'on')
  1335. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  1336. fprintf(fid,'<g id="%s" clip-path="url(#%s)" %s>\n', createId, clippingIdString, filterString);
  1337. else
  1338. fprintf(fid,'<g id="%s" %s>\n', createId, filterString);
  1339. end
  1340. if ~isempty(filterString)
  1341. % Workaround for Inkscape filter bug
  1342. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  1343. end
  1344. line2svg(fid,groupax,axpos,x,y,scolorname,linestyle,linewidth)
  1345. % put the markers into a subgroup of the lines
  1346. fprintf(fid,'<g>\n');
  1347. switch marker
  1348. case 'none';
  1349. case '.',group=group+1;circle2svg(fid,group,axpos,x,y,markersize*0.25,'none',markeredgecolorname,linewidth);
  1350. case 'o',group=group+1;circle2svg(fid,group,axpos,x,y,markersize*0.75,markeredgecolorname,markerfacecolorname,linewidth);
  1351. case '+',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,5)+ones(length(linex),1)*[-1 1 NaN 0 0]*markersize,y'*ones(1,5)+ones(length(liney),1)*[0 0 NaN -1 1]*markersize,markeredgecolorname,'-',linewidth,markeredgecolorname, 1, 1, false);
  1352. case '*',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,11)+ones(length(linex),1)*[-1 1 NaN 0 0 NaN -0.7 0.7 NaN -0.7 0.7]*markersize,y'*ones(1,11)+ones(length(liney),1)*[0 0 NaN -1 1 NaN 0.7 -0.7 NaN -0.7 0.7]*markersize,markeredgecolorname,'-',linewidth,markeredgecolorname, 1, 1, false);
  1353. case 'x',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,5)+ones(length(linex),1)*[-0.7 0.7 NaN -0.7 0.7]*markersize,y'*ones(1,5)+ones(length(liney),1)*[0.7 -0.7 NaN -0.7 0.7]*markersize,markeredgecolorname,'-',linewidth,markeredgecolorname, 1, 1, false);
  1354. %% Octave keeps s, d, p and h in the HandleGraphics object, for the square, diamond, pentagram, and hexagram markers, respectively -- Jakob Malm
  1355. case {'square', 's'},group=group+1;patch2svg(fid,group,axpos,x'*ones(1,5)+ones(length(linex),1)*[-1 -1 1 1 -1]*markersize,y'*ones(1,5)+ones(length(liney),1)*[-1 1 1 -1 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1356. case {'diamond', 'd'},group=group+1;patch2svg(fid,group,axpos,x'*ones(1,5)+ones(length(linex),1)*[-0.7071 0 0.7071 0 -0.7071]*markersize,y'*ones(1,5)+ones(length(liney),1)*[0 1 0 -1 0]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1357. case {'pentagram', 'p'},group=group+1;patch2svg(fid,group,axpos,...
  1358. x'*ones(1,11)+ones(length(linex),1)*[0 0.1180 0.5 0.1910 0.3090 0 -0.3090 -0.1910 -0.5 -0.1180 0]*1.3*markersize,...
  1359. y'*ones(1,11)+ones(length(liney),1)*[-0.5257 -0.1625 -0.1625 0.0621 0.4253 0.2008 0.4253 0.0621 -0.1625 -0.1625 -0.5257]*1.3*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1360. case {'hexagram', 'h'},group=group+1;patch2svg(fid,group,axpos,...
  1361. x'*ones(1,13)+ones(length(linex),1)*[0 0.2309 0.6928 0.4619 0.6928 0.2309 0 -0.2309 -0.6928 -0.4619 -0.6928 -0.2309 0]*1*markersize,...
  1362. y'*ones(1,13)+ones(length(liney),1)*[0.8 0.4 0.4 0 -0.4 -0.4 -0.8 -0.4 -0.4 0 0.4 0.4 0.8]*1*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1363. case '^',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[-1 1 0 -1]*markersize,y'*ones(1,4)+ones(length(liney),1)*[0.577 0.577 -0.837 0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1364. case 'v',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[-1 1 0 -1]*markersize,y'*ones(1,4)+ones(length(liney),1)*[-0.577 -0.577 0.837 -0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1365. case '<',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[0.577 0.577 -0.837 0.577]*markersize,y'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1366. case '>',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[-0.577 -0.577 0.837 -0.577]*markersize,y'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1367. end
  1368. % close the marker group
  1369. fprintf(fid,'</g>\n');
  1370. animation2svg(fid, axchild(i));
  1371. % close the line group
  1372. fprintf(fid,'</g>\n');
  1373. elseif strcmp(get(axchild(i),'Type'),'patch')
  1374. flat_shading = 1;
  1375. cmap=get(id,'Colormap');
  1376. pointc = get(axchild(i),'FaceVertexCData');
  1377. if isempty(pointc)
  1378. % Workaround for octave
  1379. pointc=get(axchild(i),'CData');
  1380. end
  1381. % Scale color if scaled color mapping is turned on
  1382. if strcmp(get(axchild(i),'CDataMapping'),'scaled')
  1383. clim=get(ax,'CLim');
  1384. pointc=(pointc-clim(1))/(clim(2)-clim(1))*(size(cmap,1)-1)+1;
  1385. end
  1386. % Limit index to smallest or biggest color index
  1387. pointc=max(pointc,1);
  1388. pointc=min(pointc,size(cmap,1));
  1389. if ~ischar(get(axchild(i),'FaceAlpha'))
  1390. face_opacity = get(axchild(i),'FaceAlpha');
  1391. else
  1392. face_opacity = 1.0;
  1393. end
  1394. if ~ischar(get(axchild(i),'EdgeAlpha'))
  1395. edge_opacity = get(axchild(i),'EdgeAlpha');
  1396. else
  1397. edge_opacity = 1.0;
  1398. end
  1399. linestyle = get(axchild(i),'LineStyle');
  1400. linewidth = get(axchild(i),'LineWidth');
  1401. marker = get(axchild(i),'Marker');
  1402. markeredgecolor=get(axchild(i),'MarkerEdgeColor');
  1403. markersize=get(axchild(i),'MarkerSize')/1.5;
  1404. points=get(axchild(i),'Vertices')';
  1405. if strcmp(get(ax,'XScale'),'log')
  1406. points(1,:)=log10(points(1,:));
  1407. end
  1408. if strcmp(get(ax,'YScale'),'log')
  1409. points(2,:)=log10(points(2,:));
  1410. end
  1411. % TODO LogZ
  1412. if size(points,1)==2
  1413. [x,y,z] = project(points(1,:),points(2,:),zeros(size(points(1,:))),projection);
  1414. else
  1415. [x,y,z] = project(points(1,:),points(2,:),points(3,:),projection);
  1416. end
  1417. x = (x*axpos(3)+axpos(1))*paperpos(3);
  1418. y = (1-(y*axpos(4)+axpos(2)))*paperpos(4);
  1419. faces = get(axchild(i),'Faces');
  1420. face_index = 1:size(faces,1);
  1421. if size(points,1)==3;
  1422. [z,face_index]=sort(sum(z(faces(:,:)),2));
  1423. faces=faces(face_index,:);
  1424. end
  1425. markerOverlap = 0;
  1426. if ~strcmp(linestyle, 'none')
  1427. markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels'));
  1428. end
  1429. if ~strcmp(marker, 'none')
  1430. markerOverlap = max(markerOverlap, convertunit(markersize, 'points', 'pixels'));
  1431. end
  1432. boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap];
  1433. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement);
  1434. if strcmp(get(axchild(i),'Clipping'),'on')
  1435. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  1436. fprintf(fid,'<g id="%s" clip-path="url(#%s)" %s>\n', createId, clippingIdString, filterString);
  1437. else
  1438. fprintf(fid,'<g id="%s" %s>\n', createId, filterString);
  1439. end
  1440. if ~isempty(filterString)
  1441. % Workaround for Inkscape filter bug
  1442. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  1443. end
  1444. for p = 1:size(faces,1)
  1445. if ischar(get(axchild(i),'FaceColor'))
  1446. if strcmp(get(axchild(i),'FaceColor'),'texturemap')
  1447. facecolorname='none'; % TO DO: texture map
  1448. elseif strcmp(get(axchild(i),'FaceColor'),'none')
  1449. facecolorname='none';
  1450. else
  1451. if size(pointc,1)==1
  1452. facecolor = pointc;
  1453. elseif size(pointc,1)==size(faces,1)
  1454. if strcmp(get(axchild(i),'FaceColor'),'flat')
  1455. facecolor = pointc(face_index(p),:);
  1456. else
  1457. facecolor = pointc(face_index(p),:);
  1458. cdata = pointc(face_index(p),:); % TO DO: color interpolation
  1459. flat_shading = 0;
  1460. end
  1461. elseif size(pointc,1)==size(points,2)
  1462. if strcmp(get(axchild(i),'FaceColor'),'flat')
  1463. facecolor = pointc(faces(p,1),:);
  1464. else
  1465. facecolor = pointc(faces(p,1));
  1466. cdata = pointc(faces(p,:),:);
  1467. flat_shading = 0;
  1468. end
  1469. else
  1470. error('Unsupported color handling for patches.');
  1471. end
  1472. if ~isnan(facecolor)
  1473. if size(facecolor,2)==1
  1474. facecolorname = ['#' colorname(ceil(facecolor),:)];
  1475. else
  1476. if strcmp(get(axchild(i),'FaceColor'),'flat') % Bugfix 27.01.2008
  1477. facecolorname = searchcolor(id,facecolor/64);
  1478. else
  1479. facecolorname = searchcolor(id,facecolor);
  1480. end
  1481. end
  1482. else
  1483. facecolorname='none';
  1484. end
  1485. end
  1486. else
  1487. facecolorname = searchcolor(id,get(axchild(i),'FaceColor'));
  1488. end
  1489. if ischar(get(axchild(i),'EdgeColor'))
  1490. if strcmp(get(axchild(i),'EdgeColor'),'none')
  1491. edgecolorname = 'none';
  1492. else
  1493. if size(pointc,1)==1
  1494. edgecolor = pointc;
  1495. elseif size(pointc,1)==size(faces,1)
  1496. edgecolor = pointc(p,:);
  1497. elseif size(pointc,1)==size(points,2)
  1498. if strcmp(get(axchild(i),'EdgeColor'),'flat')
  1499. edgecolor = pointc(faces(p,1));
  1500. else
  1501. edgecolor = pointc(faces(p,1)); % TO DO: color interpolation
  1502. end
  1503. else
  1504. error('Unsupported color handling for patches.');
  1505. end
  1506. if ~isnan(edgecolor)
  1507. if size(edgecolor,2)==1
  1508. edgecolorname = ['#' colorname(ceil(edgecolor),:)];
  1509. else
  1510. if strcmp(get(axchild(i),'EdgeColor'),'flat') % Bugfix 27.01.2008
  1511. edgecolorname = searchcolor(id,edgecolor/64);
  1512. else
  1513. edgecolorname = searchcolor(id,edgecolor);
  1514. end
  1515. end
  1516. else
  1517. edgecolorname = 'none';
  1518. end
  1519. end
  1520. else
  1521. edgecolorname = searchcolor(id,get(axchild(i),'EdgeColor'));
  1522. end
  1523. % Close a patch if the coordinates do not contain NaNs
  1524. if any(isnan(x)) || any(isnan(y))
  1525. closed = false;
  1526. else
  1527. closed = true;
  1528. end
  1529. if flat_shading
  1530. patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), facecolorname, linestyle, linewidth, edgecolorname, face_opacity, edge_opacity, closed)
  1531. else
  1532. gouraud_patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), cdata, linestyle, linewidth, edgecolorname, face_opacity, edge_opacity, id)
  1533. end
  1534. if ~strcmp(marker, 'none')
  1535. xmarker = x(faces(p,:));
  1536. ymarker = y(faces(p,:));
  1537. % put the markers into a subgroup of the lines
  1538. fprintf(fid,'<g>\n');
  1539. if ischar(markeredgecolor)
  1540. switch markeredgecolor
  1541. case 'none',markeredgecolorname='none';
  1542. otherwise,
  1543. % if markeredgecolorname is 'auto' or something
  1544. % else set the markeredgecolorname to the line color
  1545. markeredgecolorname = selectColor(axchild(i), id, p, points, pointc, ...
  1546. colorname, faces, 'MarkerEdgeColor');
  1547. end
  1548. else
  1549. markeredgecolorname=searchcolor(id,markeredgecolor);
  1550. end
  1551. markerfacecolor=get(axchild(i),'MarkerFaceColor');
  1552. if ischar(markerfacecolor)
  1553. switch markerfacecolor
  1554. case 'none',markerfacecolorname='none';
  1555. otherwise,
  1556. markerfacecolorname = selectColor(axchild(i), id, p, points, pointc, ...
  1557. colorname, faces,'MarkerFaceColor');
  1558. end
  1559. else
  1560. markerfacecolorname=searchcolor(id,markerfacecolor);
  1561. end
  1562. switch marker
  1563. case 'none';
  1564. case '.',group=group+1;circle2svg(fid,group,axpos,xmarker,ymarker,markersize*0.25,'none',markeredgecolorname,linewidth);
  1565. case 'o',group=group+1;circle2svg(fid,group,axpos,xmarker,ymarker,markersize*0.75,markeredgecolorname,markerfacecolorname,linewidth);
  1566. case '+',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,5)+ones(length(linex),1)*[-1 1 NaN 0 0]*markersize,ymarker'*ones(1,5)+ones(length(liney),1)*[0 0 NaN -1 1]*markersize,markeredgecolorname,'-',linewidth,markeredgecolorname, 1, 1, false);
  1567. case '*',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,11)+ones(length(linex),1)*[-1 1 NaN 0 0 NaN -0.7 0.7 NaN -0.7 0.7]*markersize,ymarker'*ones(1,11)+ones(length(liney),1)*[0 0 NaN -1 1 NaN 0.7 -0.7 NaN -0.7 0.7]*markersize,markeredgecolorname,'-',linewidth,markeredgecolorname, 1, 1, false);
  1568. case 'x',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,5)+ones(length(linex),1)*[-0.7 0.7 NaN -0.7 0.7]*markersize,ymarker'*ones(1,5)+ones(length(liney),1)*[0.7 -0.7 NaN -0.7 0.7]*markersize,markeredgecolorname,'-',linewidth,markeredgecolorname, 1, 1, false);
  1569. %% Octave keeps s, d, p and h in the HandleGraphics object, for the square, diamond, pentagram, and hexagram markers, respectively -- Jakob Malm
  1570. case {'square', 's'},group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,5)+ones(length(linex),1)*[-1 -1 1 1 -1]*markersize,ymarker'*ones(1,5)+ones(length(liney),1)*[-1 1 1 -1 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1571. case {'diamond', 'd'},group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,5)+ones(length(linex),1)*[-0.7071 0 0.7071 0 -0.7071]*markersize,ymarker'*ones(1,5)+ones(length(liney),1)*[0 1 0 -1 0]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1572. case {'pentagram', 'p'},group=group+1;patch2svg(fid,group,axpos,...
  1573. xmarker'*ones(1,11)+ones(length(linex),1)*[0 0.1180 0.5 0.1910 0.3090 0 -0.3090 -0.1910 -0.5 -0.1180 0]*1.3*markersize,...
  1574. ymarker'*ones(1,11)+ones(length(liney),1)*[-0.5257 -0.1625 -0.1625 0.0621 0.4253 0.2008 0.4253 0.0621 -0.1625 -0.1625 -0.5257]*1.3*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1575. case {'hexagram', 'h'},group=group+1;patch2svg(fid,group,axpos,...
  1576. xmarker'*ones(1,13)+ones(length(linex),1)*[0 0.2309 0.6928 0.4619 0.6928 0.2309 0 -0.2309 -0.6928 -0.4619 -0.6928 -0.2309 0]*1*markersize,...
  1577. ymarker'*ones(1,13)+ones(length(liney),1)*[0.8 0.4 0.4 0 -0.4 -0.4 -0.8 -0.4 -0.4 0 0.4 0.4 0.8]*1*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1578. case '^',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,4)+ones(length(linex),1)*[-1 1 0 -1]*markersize,ymarker'*ones(1,4)+ones(length(liney),1)*[0.577 0.577 -0.837 0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1579. case 'v',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,4)+ones(length(linex),1)*[-1 1 0 -1]*markersize,ymarker'*ones(1,4)+ones(length(liney),1)*[-0.577 -0.577 0.837 -0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1580. case '<',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,4)+ones(length(linex),1)*[0.577 0.577 -0.837 0.577]*markersize,ymarker'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1581. case '>',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,4)+ones(length(linex),1)*[-0.577 -0.577 0.837 -0.577]*markersize,ymarker'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true);
  1582. end
  1583. % close the marker group
  1584. fprintf(fid,'</g>\n');
  1585. end
  1586. end
  1587. fprintf(fid,'</g>\n');
  1588. elseif strcmp(get(axchild(i),'Type'),'surface')
  1589. flat_shading = 1;
  1590. cmap=get(id,'Colormap');
  1591. [faces,points,pointc,alpha]=surface2patch(axchild(i));
  1592. points=points';
  1593. % Scale color if scaled color mapping is turned on
  1594. if strcmp(get(axchild(i),'CDataMapping'),'scaled')
  1595. clim=get(ax,'CLim');
  1596. pointc=(pointc-clim(1))/(clim(2)-clim(1))*(size(cmap,1)-1)+1;
  1597. end
  1598. % Limit index to smallest or biggest color index
  1599. pointc=max(pointc,1);
  1600. if ~ischar(get(axchild(i),'FaceAlpha'))
  1601. face_opacity = get(axchild(i),'FaceAlpha');
  1602. elseif strcmp(get(axchild(i),'FaceAlpha'),'flat')
  1603. face_opacity = alpha;
  1604. switch get(axchild(i),'AlphaDataMapping')
  1605. case {'direct'}
  1606. face_opacity = 1.0; % TODO
  1607. case {'scaled'}
  1608. alim=get(ax,'ALim');
  1609. face_opacity=(face_opacity-alim(1))/(alim(2)-alim(1));
  1610. case {'none'}
  1611. % Clip alpha data
  1612. face_opacity = min(1, face_opacity);
  1613. face_opacity = max(0, face_opacity);
  1614. otherwise
  1615. error(['Unsupported AlphaDataMapping identifier ''' get(axchild(i),'AlphaDataMapping') '''.']);
  1616. end
  1617. else
  1618. face_opacity = 1.0;
  1619. end
  1620. if ~ischar(get(axchild(i),'EdgeAlpha'))
  1621. edge_opacity = get(axchild(i),'EdgeAlpha');
  1622. else
  1623. edge_opacity = 1.0;
  1624. end
  1625. pointc=min(pointc,size(cmap,1));
  1626. linestyle=get(axchild(i),'LineStyle');
  1627. linewidth=get(axchild(i),'LineWidth');
  1628. if strcmp(get(ax,'XScale'),'log')
  1629. points(1,:)=log10(points(1,:));
  1630. end
  1631. if strcmp(get(ax,'YScale'),'log')
  1632. points(2,:)=log10(points(2,:));
  1633. end
  1634. if size(points,1)==3
  1635. if strcmp(get(ax,'ZScale'),'log')
  1636. points(3,:)=log10(points(3,:));
  1637. end
  1638. end
  1639. if size(points,1)==3
  1640. [x,y,z] = project(points(1,:),points(2,:),points(3,:),projection);
  1641. else
  1642. [x,y,z] = project(points(1,:),points(2,:),zeros(size(points(1,:))),projection);
  1643. end
  1644. x = (x*axpos(3)+axpos(1))*paperpos(3);
  1645. y = (1-(y*axpos(4)+axpos(2)))*paperpos(4);
  1646. face_index = 1:size(faces,1);
  1647. if size(points,1)==3;
  1648. [z,face_index]=sort(sum(z(faces(:,:)),2));
  1649. faces=faces(face_index,:);
  1650. end
  1651. markerOverlap = 0;
  1652. if ~strcmp(linestyle, 'none')
  1653. markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels'));
  1654. end
  1655. boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap];
  1656. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement);
  1657. if strcmp(get(axchild(i),'Clipping'),'on')
  1658. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  1659. fprintf(fid,'<g clip-path="url(#%s)" id="%s" %s>\n',clippingIdString, createId, filterString);
  1660. else
  1661. fprintf(fid,'<g id="%s" %s>\n', createId, filterString);
  1662. end
  1663. if ~isempty(filterString)
  1664. % Workaround for Inkscape filter bug
  1665. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  1666. end
  1667. for p=1:size(faces,1)
  1668. if ischar(get(axchild(i),'FaceColor'))
  1669. if strcmp(get(axchild(i),'FaceColor'),'texturemap')
  1670. facecolorname='none'; % TO DO: texture map
  1671. elseif strcmp(get(axchild(i),'FaceColor'),'none')
  1672. facecolorname='none';
  1673. else
  1674. if size(pointc,1)==1
  1675. facecolor = pointc;
  1676. elseif size(pointc,1)==size(faces,1)
  1677. facecolor = pointc(face_index(p),:);
  1678. elseif size(pointc,1)==size(points,2)
  1679. if strcmp(get(axchild(i),'FaceColor'),'flat')
  1680. facecolor = pointc(faces(p,1));
  1681. else
  1682. facecolor = pointc(faces(p,1));
  1683. cdata = pointc(faces(p,:));
  1684. flat_shading = 0;
  1685. end
  1686. else
  1687. error('Unsupported color handling for patches.');
  1688. end
  1689. if ~isnan(facecolor)
  1690. if size(facecolor,2)==1
  1691. facecolorname = ['#' colorname(ceil(facecolor),:)];
  1692. else
  1693. facecolorname = searchcolor(id,facecolor);
  1694. end
  1695. else
  1696. facecolorname='none';
  1697. end
  1698. end
  1699. else
  1700. facecolorname = searchcolor(id,get(axchild(i),'FaceColor'));
  1701. end
  1702. if size(face_opacity,1)==1
  1703. face_opacity_value = face_opacity;
  1704. elseif size(face_opacity,1)==size(faces,1)
  1705. face_opacity_value = face_opacity(p,:);
  1706. elseif size(face_opacity,1)==size(points,2)
  1707. face_opacity_value = face_opacity(faces(p,1));
  1708. else
  1709. error('Unsupported face alpha value handling for patches.');
  1710. end
  1711. if ischar(get(axchild(i),'EdgeColor'))
  1712. if strcmp(get(axchild(i),'EdgeColor'),'none')
  1713. edgecolorname = 'none';
  1714. else
  1715. if size(pointc,1)==1
  1716. edgecolor = pointc;
  1717. elseif size(pointc,1)==size(faces,1)
  1718. edgecolor = pointc(p,:);
  1719. elseif size(pointc,1)==size(points,2)
  1720. if strcmp(get(axchild(i),'EdgeColor'),'flat')
  1721. edgecolor = pointc(faces(p,1));
  1722. else
  1723. edgecolor = pointc(faces(p,1)); % TO DO: color interpolation
  1724. end
  1725. else
  1726. error('Unsupported color handling for patches.');
  1727. end
  1728. if ~isnan(edgecolor)
  1729. if size(edgecolor,2)==1
  1730. edgecolorname = ['#' colorname(ceil(edgecolor),:)];
  1731. else
  1732. edgecolorname = searchcolor(id,edgecolor);
  1733. end
  1734. else
  1735. edgecolorname = 'none';
  1736. end
  1737. end
  1738. else
  1739. edgecolorname = searchcolor(id,get(axchild(i),'EdgeColor'));
  1740. end
  1741. if flat_shading
  1742. patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), facecolorname, linestyle, linewidth, edgecolorname, face_opacity_value, edge_opacity, false)
  1743. else
  1744. gouraud_patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), cdata, linestyle, linewidth, edgecolorname, face_opacity_value, edge_opacity,id)
  1745. end
  1746. end
  1747. fprintf(fid,'</g>\n');
  1748. elseif strcmp(get(axchild(i),'Type'),'rectangle')
  1749. scolorname=searchcolor(id,get(axchild(i),'EdgeColor'));
  1750. fcolorname=searchcolor(id,get(axchild(i),'FaceColor'));
  1751. linewidth=get(axchild(i),'LineWidth');
  1752. position = get(axchild(i),'Position');
  1753. posx = [position(1) position(1)+position(3)];
  1754. if strcmp(get(ax,'XScale'),'log')
  1755. posx(find(posx<=0)) = NaN;
  1756. posx=log10(posx);
  1757. end
  1758. posy = [position(2) position(2)+position(4)];
  1759. if strcmp(get(ax,'YScale'),'log')
  1760. posy(find(posy<=0)) = NaN;
  1761. posy=log10(posy);
  1762. end
  1763. posz=[0 0];
  1764. linestyle = get(axchild(i),'LineStyle');
  1765. pattern = lineStyle2svg(linestyle, linewidth);
  1766. [x,y,z] = project(posx,posy,posz,projection);
  1767. x = (x*axpos(3)+axpos(1))*paperpos(3);
  1768. y = (1-(y*axpos(4)+axpos(2)))*paperpos(4);
  1769. rect = [min(x) min(y) max(x)-min(x) max(y)-min(y)];
  1770. curvature = get(axchild(i),'Curvature');
  1771. curvature(1) = curvature(1)*rect(3)*0.5;
  1772. curvature(2) = curvature(2)*rect(4)*0.5;
  1773. markerOverlap = 0;
  1774. if ~strcmp(linestyle, 'none')
  1775. markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels'));
  1776. end
  1777. boundingBoxElement = rect + [-markerOverlap -markerOverlap 2*markerOverlap 2*markerOverlap];
  1778. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement);
  1779. % put a rectangle into a group with its markers
  1780. if strcmp(get(axchild(i),'Clipping'),'on')
  1781. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  1782. fprintf(fid,'<g id="%s" clip-path="url(#%s)" %s>\n', createId, clippingIdString, filterString);
  1783. else
  1784. fprintf(fid,'<g id="%s" %s>\n', createId, filterString);
  1785. end
  1786. if ~isempty(filterString)
  1787. % Workaround for Inkscape filter bug
  1788. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  1789. end
  1790. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" rx="%0.3f" ry="%0.3f" fill="%s" stroke="%s" stroke-width="%0.1fpt" %s />\n',...
  1791. rect(1), rect(2), rect(3), rect(4), curvature(1), curvature(2), fcolorname, scolorname, linewidth, pattern);
  1792. % close the rectangle group
  1793. fprintf(fid,'</g>\n');
  1794. elseif strcmp(get(axchild(i),'Type'),'text')
  1795. if PLOT2SVG_globals.octave
  1796. extent = [0 0 0 0];
  1797. else
  1798. extent = get(axchild(i),'Extent');
  1799. end
  1800. margin = get(axchild(i),'Margin');
  1801. facecolor = get(axchild(i),'BackgroundColor');
  1802. edgecolor = get(axchild(i),'EdgeColor');
  1803. linewidth = get(axchild(i),'LineWidth');
  1804. linestyle = get(axchild(i),'LineStyle');
  1805. if ischar(facecolor)
  1806. if ~strcmp(facecolor,'none')
  1807. error('Illegal face color for text.');
  1808. else
  1809. facecolorname = 'none';
  1810. end
  1811. else
  1812. facecolorname = searchcolor(id, facecolor);
  1813. end
  1814. if ischar(edgecolor)
  1815. if ~strcmp(edgecolor,'none')
  1816. error('Illegal edge color for text.');
  1817. else
  1818. edgecolorname = 'none';
  1819. end
  1820. else
  1821. edgecolorname = searchcolor(id, edgecolor);
  1822. end
  1823. extentx = [extent(1) extent(1)+extent(3)];
  1824. extenty = [extent(2) extent(2)+extent(4)];
  1825. extentz = [0 0];
  1826. [x,y,z] = project(extentx,extenty,extentz,projection);
  1827. x = (x*axpos(3)+axpos(1))*paperpos(3);
  1828. y = (1-(y*axpos(4)+axpos(2)))*paperpos(4);
  1829. box = [min(x)-margin min(y)-margin max(x)-min(x)+2*margin max(y)-min(y)+2*margin];
  1830. markerOverlap = 0;
  1831. if ~strcmp(linestyle, 'none')
  1832. markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels'));
  1833. end
  1834. boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap];
  1835. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement);
  1836. if strcmp(get(axchild(i),'Clipping'),'on') && ~PLOT2SVG_globals.octave
  1837. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  1838. fprintf(fid,'<g id="%s" clip-path="url(#%s)" %s>\n', createId, clippingIdString, filterString);
  1839. else
  1840. fprintf(fid,'<g id="%s" %s>\n', createId, filterString);
  1841. end
  1842. if ~isempty(filterString)
  1843. % Workaround for Inkscape filter bug
  1844. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  1845. end
  1846. if ~strcmp(edgecolorname, 'none') || ~strcmp(facecolorname, 'none')
  1847. pattern = lineStyle2svg(linestyle, linewidth);
  1848. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="%s" stroke="%s" stroke-width="%0.1fpt" %s />\n', ...
  1849. box(1), box(2), box(3), box(4), facecolorname, edgecolorname, linewidth, pattern);
  1850. end
  1851. text2svg(fid,1,axpos,paperpos,axchild(i),ax,projection)
  1852. fprintf(fid,'</g>\n');
  1853. elseif strcmp(get(axchild(i),'Type'),'image')
  1854. cmap=get(id,'Colormap');
  1855. pointx=get(axchild(i),'XData');
  1856. pointy=get(axchild(i),'YData');
  1857. % If the XData is a vector we only use start and stop for the image
  1858. if (size(pointx, 1) > 2) || (size(pointx, 2) > 1)
  1859. pointx = [pointx(1) pointx(end)];
  1860. end
  1861. if (size(pointy, 1) > 2) || (size(pointy, 2) > 1)
  1862. pointy = [pointy(1) pointy(end)];
  1863. end
  1864. if (size(pointx, 1) > 1) && (size(pointy, 1) > 1)
  1865. [x,y,z] = project(pointx,zeros(size(pointx)),zeros(size(pointx)),projection);
  1866. else
  1867. [x,y_dummy,z] = project(pointx,zeros(size(pointx)),zeros(size(pointx)),projection);
  1868. [x_dummy,y,z] = project(zeros(size(pointy)),pointy,zeros(size(pointy)),projection);
  1869. end
  1870. pointc=get(axchild(i),'CData');
  1871. %pointcclass = class(pointc); % Bugfix proposed by Tom
  1872. if strcmp(get(axchild(i),'CDataMapping'),'scaled')
  1873. clim=get(ax,'CLim');
  1874. pointc=(pointc-clim(1))/(clim(2)-clim(1))*(size(cmap,1) - 1) + 1; % Bugfix proposed by Tom
  1875. %pointcclass = 'double'; % since range is now [0->size(cmap,1)-1] % Bugfix proposed by Tom
  1876. end
  1877. data_aspect_ratio = get(ax,'DataAspectRatio');
  1878. if length(x) == 2
  1879. if size(pointc, 2) == 1
  1880. halfwidthx = abs(x(2) - x(1)) * data_aspect_ratio(1);
  1881. else
  1882. halfwidthx = abs(x(2) - x(1))/(size(pointc,2) - 1);
  1883. end
  1884. else
  1885. halfwidthx = data_aspect_ratio(1);
  1886. end
  1887. if length(y) == 2
  1888. if size(pointc, 1) == 1
  1889. halfwidthy = abs(y(2) - y(1)) * data_aspect_ratio(2);
  1890. else
  1891. halfwidthy = abs(y(2) - y(1))/(size(pointc,1) - 1);
  1892. end
  1893. else
  1894. halfwidthy = data_aspect_ratio(2);
  1895. end
  1896. if length(pointx) > 1
  1897. if xor(strcmp(get(ax,'XDir'),'reverse'), pointx(1) > pointx(2))
  1898. if ndims(pointc) < 3
  1899. pointc=fliplr(pointc);
  1900. elseif ndims(pointc) == 3
  1901. for j = 1:size(pointc,3)
  1902. pointc(:,:,j)=fliplr(pointc(:,:,j));
  1903. end
  1904. else
  1905. error('Invalid number of dimensions of data.');
  1906. end
  1907. end
  1908. end
  1909. if length(pointy) > 1
  1910. if xor(strcmp(get(ax,'YDir'),'reverse'), pointy(1) > pointy(2))
  1911. if ndims(pointc) < 3
  1912. pointc=flipud(pointc);
  1913. elseif ndims(pointc) == 3
  1914. for j = [1:size(pointc,3)]
  1915. pointc(:,:,j)=flipud(pointc(:,:,j));
  1916. end
  1917. else
  1918. error('Invalid number of dimensions of data.');
  1919. end
  1920. end
  1921. end
  1922. % pointc = cast(pointc,pointcclass); % Bugfix proposed by Tom
  1923. % Function 'cast' is not supported by old Matlab versions
  1924. if (~isa(pointc, 'double') && ~isa(pointc, 'single'))
  1925. if strcmp(get(axchild(i),'CDataMapping'),'scaled')
  1926. pointc = double(pointc);
  1927. else
  1928. pointc = double(pointc) + 1;
  1929. end
  1930. end
  1931. if ndims(pointc) ~= 3
  1932. pointc = max(min(round(double(pointc)),size(cmap,1)),1);
  1933. end
  1934. CameraUpVector = get(ax,'CameraUpVector');
  1935. filename = [PLOT2SVG_globals.basefilename sprintf('%03d',PLOT2SVG_globals.figurenumber) '.' PLOT2SVG_globals.pixelfiletype];
  1936. PLOT2SVG_globals.figurenumber = PLOT2SVG_globals.figurenumber + 1;
  1937. if isempty(PLOT2SVG_globals.basefilepath)
  1938. current_path = pwd;
  1939. else
  1940. current_path = PLOT2SVG_globals.basefilepath;
  1941. end
  1942. if exist(fullfile(current_path,filename),'file')
  1943. lastwarn('');
  1944. delete(filename);
  1945. if strcmp(lastwarn,'File not found or permission denied.')
  1946. error('Cannot write image file. Make sure that no image is opened in an other program.')
  1947. end
  1948. end
  1949. if ndims(pointc) < 3
  1950. pointc = flipud(pointc);
  1951. elseif ndims(pointc) == 3
  1952. for j = size(pointc,3)
  1953. pointc(:,:,j)=flipud(pointc(:,:,j));
  1954. end
  1955. else
  1956. error('Invalid number of dimensions of data.');
  1957. end
  1958. if ndims(pointc) == 3
  1959. % pointc is not indexed
  1960. imwrite(pointc,fullfile(PLOT2SVG_globals.basefilepath,filename),PLOT2SVG_globals.pixelfiletype);
  1961. else
  1962. % pointc is probably indexed
  1963. if PLOT2SVG_globals.octave
  1964. pointc = max(2, pointc);
  1965. end
  1966. imwrite(pointc,cmap,fullfile(PLOT2SVG_globals.basefilepath,filename),PLOT2SVG_globals.pixelfiletype);
  1967. end
  1968. lx=(size(pointc,2)*halfwidthx)*axpos(3)*paperpos(3);
  1969. ly=(size(pointc,1)*halfwidthy)*axpos(4)*paperpos(4);
  1970. if strcmp(get(ax,'DataAspectRatioMode'),'manual')
  1971. pointsx=((min(x) - halfwidthx/2)*axpos(3)+axpos(1))*paperpos(3);
  1972. pointsy=(1-((max(y) + halfwidthy/2)*axpos(4)+axpos(2)))*paperpos(4);
  1973. else
  1974. pointsx=axpos(1)*paperpos(3);
  1975. pointsy=(1-(axpos(4)+axpos(2)))*paperpos(4);
  1976. end
  1977. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxAxes);
  1978. if strcmp(get(axchild(i),'Clipping'),'on')
  1979. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  1980. fprintf(fid,'<g id="%s" clip-path="url(#%s)" %s>\n', createId, clippingIdString, filterString);
  1981. if ~isempty(filterString)
  1982. % Workaround for Inkscape filter bug
  1983. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  1984. end
  1985. fprintf(fid,'<image x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" image-rendering="optimizeSpeed" preserveAspectRatio="none" xlink:href="%s" />\n', pointsx, pointsy, lx, ly, filename);
  1986. fprintf(fid,'</g>\n');
  1987. else
  1988. fprintf(fid,'<g id="%s" %s>\n', createId, filterString);
  1989. if ~isempty(filterString)
  1990. % Workaround for Inkscape filter bug
  1991. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  1992. end
  1993. fprintf(fid,'<image x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" image-rendering="optimizeSpeed" preserveAspectRatio="none" xlink:href="%s" />\n', pointsx, pointsy, lx, ly, filename);
  1994. fprintf(fid,'</g>\n');
  1995. end
  1996. elseif strcmp(get(axchild(i),'Type'), 'hggroup')
  1997. % handle group types (like error bars)
  1998. % FIXME: they are not yet perfectly handled, there are more options
  1999. % that are not used
  2000. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxAxes);
  2001. if strcmp(get(axchild(i),'Clipping'),'on')
  2002. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  2003. fprintf(fid,'<g id="%s" clip-path="url(#%s)" %s>\n', createId, clippingIdString, filterString);
  2004. else
  2005. fprintf(fid, '<g id="%s" %s>', createId, filterString);
  2006. end
  2007. if ~isempty(filterString)
  2008. % Workaround for Inkscape filter bug
  2009. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  2010. end
  2011. group=axchild2svg(fid,id,axIdString,ax,group,paperpos,get(axchild(i), 'Children'),axpos,groupax,projection,boundingBoxAxes);
  2012. fprintf(fid, '</g>');
  2013. elseif strcmp(get(axchild(i),'Type'), 'hgtransform')
  2014. if strcmpi(get(axchild(i), 'Visible'), 'on')
  2015. [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxAxes);
  2016. if strcmp(get(axchild(i),'Clipping'),'on')
  2017. clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString);
  2018. fprintf(fid,'<g id="%s" clip-path="url(#%s)" %s>\n', createId, clippingIdString, filterString);
  2019. else
  2020. fprintf(fid, '<g id="%s" %s>', createId, filterString);
  2021. end
  2022. if ~isempty(filterString)
  2023. % Workaround for Inkscape filter bug
  2024. fprintf(fid,'<rect x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" fill="none" stroke="none" />\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4));
  2025. end
  2026. group=axchild2svg(fid,id,axIdString,ax,group,paperpos,get(axchild(i), 'Children'),axpos,groupax,projection,boundingBoxAxes);
  2027. fprintf(fid, '</g>');
  2028. end
  2029. else
  2030. disp([' Warning: Unhandled child type: ' get(axchild(i),'Type')]);
  2031. end
  2032. end
  2033. function result = selectColor(axchild, id, p, points, pointc, colorname, faces, type)
  2034. if size(pointc, 1) == 1
  2035. color = pointc;
  2036. elseif size(pointc, 1) == size(faces, 1)
  2037. color = pointc(p,:);
  2038. elseif size(pointc, 1) == size(points, 2)
  2039. if strcmp(get(axchild, type), 'flat')
  2040. color = pointc(faces(p, 1));
  2041. else
  2042. color = pointc(faces(p, 1)); % TO DO: color interpolation
  2043. end
  2044. else
  2045. error('Unsupported color handling for patches.');
  2046. end
  2047. if ~isnan(color)
  2048. if size(color, 2) == 1
  2049. result = ['#' colorname(ceil(color), :)];
  2050. else
  2051. if strcmp(get(axchild, type), 'flat') % Bugfix 27.01.2008
  2052. result = searchcolor(id, color / 64);
  2053. else
  2054. result = searchcolor(id, color);
  2055. end
  2056. end
  2057. else
  2058. result = 'none';
  2059. end
  2060. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2061. % create a patch (filled area)
  2062. function patch2svg(fid,group,axpos,xtot,ytot,scolorname,style,width, edgecolorname, face_opacity, edge_opacity, closed)
  2063. if closed
  2064. type = 'polygon';
  2065. else
  2066. type = 'polyline';
  2067. end
  2068. pattern = lineStyle2svg(style, width);
  2069. if strcmp(style, 'none')
  2070. edge_opacity = 0.0;
  2071. end
  2072. for i=1:size(xtot,1)
  2073. x=xtot(i,:);
  2074. y=ytot(i,:);
  2075. if all(~isnan(x)) && all(~isnan(y))
  2076. for j=1:20000:length(x)
  2077. xx=x(j:min(length(x),j+19999));
  2078. yy=y(j:min(length(y),j+19999));
  2079. if ~strcmp(edgecolorname,'none') || ~strcmp(scolorname,'none')
  2080. fprintf(fid,' <%s fill="%s" fill-opacity="%0.2f" stroke="%s" stroke-width="%0.1fpt" stroke-opacity="%0.2f" %s points="',...
  2081. type, scolorname, face_opacity, edgecolorname, width, edge_opacity, pattern);
  2082. fprintf(fid,'%0.3f,%0.3f ',[xx;yy]);
  2083. fprintf(fid,'"/>\n');
  2084. end
  2085. end
  2086. else
  2087. parts=find(isnan(x)+isnan(y));
  2088. if parts(1)~=1
  2089. parts=[0 parts];
  2090. end
  2091. if parts(length(parts))~=length(x)
  2092. parts=[parts length(x)+1];
  2093. end
  2094. for j=1:(length(parts)-1)
  2095. xx=x((parts(j)+1):(parts(j+1)-1));
  2096. yy=y((parts(j)+1):(parts(j+1)-1));
  2097. if ~strcmp(edgecolorname,'none') || ~strcmp(scolorname,'none')
  2098. if length(xx)~=0
  2099. fprintf(fid,' <%s fill="%s" fill-opacity="%0.2f" stroke="%s" stroke-width="%0.1fpt" stroke-opacity="%0.2f" %s points="',...
  2100. type, scolorname, face_opacity, edgecolorname, width, edge_opacity, pattern);
  2101. fprintf(fid,'%0.3f,%0.3f ',[xx;yy]);
  2102. fprintf(fid,'"/>\n');
  2103. end
  2104. end
  2105. end
  2106. end
  2107. end
  2108. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2109. % create a patch (filled area)
  2110. function gouraud_patch2svg(fid,group,axpos,xtot,ytot,cdata,style,width, edgecolorname, face_opacity, edge_opacity,id)
  2111. global colorname
  2112. pattern = lineStyle2svg(style, width);
  2113. if strcmp(style, 'none')
  2114. edge_opacity = 0.0;
  2115. end
  2116. for i=1:size(xtot,1)
  2117. x=xtot(i,:);
  2118. y=ytot(i,:);
  2119. if (any(isnan(x)) || any(isnan(y)))
  2120. fprintf('Warning: Found NaN in Gouraud patch.\n')
  2121. else
  2122. % If there are more than 2 edges always 3 edges are taken togehter
  2123. % to form a triangle
  2124. if length(x) > 2
  2125. for j = 3:length(x)
  2126. coord = [x([1 j-1 j]);y([1 j-1 j])];
  2127. face_color = cdata(1,:);
  2128. face_color2 = cdata(j-1,:);
  2129. face_color3 = cdata(j,:);
  2130. delta = coord(:,3)-coord(:,2);
  2131. if det([delta (coord(:,1)-coord(:,2))]) ~= 0
  2132. if ~isnan(face_color)
  2133. IDstring1 = createId;
  2134. IDstring2 = createId;
  2135. if size(face_color2,2)==1
  2136. face_color_name2 = ['#' colorname(ceil(face_color2),:)];
  2137. else
  2138. face_color_name2 = searchcolor(id,face_color2/64);
  2139. end
  2140. if size(face_color3,2)==1
  2141. face_color_name3 = ['#' colorname(ceil(face_color3),:)];
  2142. else
  2143. face_color_name3 = searchcolor(id,face_color3/64);
  2144. end
  2145. grad_end=(delta)*(delta'*(coord(:,1)-coord(:,2)))/(delta'*delta) + coord(:,2);
  2146. if size(face_color,2)==1
  2147. face_color_name = ['#' colorname(ceil(face_color),:)];
  2148. else
  2149. face_color_name = searchcolor(id,face_color/64);
  2150. end
  2151. fprintf(fid,'<defs>\n');
  2152. fprintf(fid,'<linearGradient id="%s" gradientUnits="userSpaceOnUse" x1="%0.3f" y1="%0.3f" x2="%0.3f" y2="%0.3f">\n',...
  2153. IDstring1, coord(1,2), coord(2,2), coord(1,3), coord(2,3));
  2154. fprintf(fid,'<stop offset="0" stop-color="%s" stop-opacity="1"/>\n',face_color_name2);
  2155. fprintf(fid,'<stop offset="1" stop-color="%s" stop-opacity="1"/>\n',face_color_name3);
  2156. fprintf(fid,'</linearGradient>\n');
  2157. fprintf(fid,'<linearGradient id="%s" gradientUnits="userSpaceOnUse" x1="%0.3f" y1="%0.3f" x2="%0.3f" y2="%0.3f">\n',...
  2158. IDstring2, coord(1,1), coord(2,1), grad_end(1), grad_end(2));
  2159. fprintf(fid,'<stop offset="0" stop-color="%s" stop-opacity="1"/>\n',face_color_name);
  2160. fprintf(fid,'<stop offset="1" stop-color="%s" stop-opacity="0"/>\n',face_color_name);
  2161. fprintf(fid,'</linearGradient>\n');
  2162. fprintf(fid,'</defs>\n');
  2163. % Open group
  2164. temp_string = sprintf('%0.3f,%0.3f ',coord);
  2165. fprintf(fid,'<g opacity="%0.2f">\n',face_opacity);
  2166. fprintf(fid,'<polyline fill="url(#%s)" stroke="none" points="%s"/>\n',IDstring1,temp_string);
  2167. fprintf(fid,'<polyline fill="url(#%s)" stroke="none" points="%s"/>\n',IDstring2,temp_string);
  2168. % Close group
  2169. fprintf(fid,'</g>\n');
  2170. end
  2171. end
  2172. end
  2173. end
  2174. % Last we draw the line around the patch
  2175. if ~strcmp(edgecolorname,'none')
  2176. fprintf(fid,'<polygon fill="none" stroke="%s" stroke-width="%0.1fpt" stroke-opacity="%0.2f" %s points="',...
  2177. edgecolorname, width, edge_opacity, pattern);
  2178. fprintf(fid,'%0.3f,%0.3f ',[x;y]);
  2179. fprintf(fid,'"/>\n');
  2180. end
  2181. end
  2182. end
  2183. function patternString = lineStyle2svg(lineStyle, lineWidth)
  2184. % Create the string for the line style
  2185. % Note: On Matlab the line style is not identical on screen and in a png.
  2186. % We will try to match with the screen format.
  2187. scaling = max(1, lineWidth * 0.4);
  2188. switch lineStyle
  2189. case '--', patternString = sprintf('stroke-dasharray="%0.1fpt,%0.1fpt"', 8*scaling, 2*scaling);
  2190. case ':', patternString = sprintf('stroke-dasharray="%0.1fpt,%0.1fpt"', 2*scaling, 2*scaling);
  2191. case '-.', patternString = sprintf('stroke-dasharray="%0.1fpt,%0.1fpt,%0.1fpt,%0.1fpt"', 8*scaling, 2*scaling, 2*scaling, 2*scaling);
  2192. otherwise, patternString = 'stroke-dasharray="none"';
  2193. end
  2194. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2195. % create a line segment
  2196. % this algorthm was optimized for large segement counts
  2197. function line2svg(fid,group,axpos,x,y,scolorname,style,width)
  2198. if ~strcmp(style,'none')
  2199. pattern = lineStyle2svg(style, width);
  2200. if (isnan(x)==zeros(size(x))&isnan(y)==zeros(size(y)))
  2201. for j=1:20000:length(x)
  2202. xx=x(j:min(length(x),j+19999));
  2203. yy=y(j:min(length(y),j+19999));
  2204. fprintf(fid,' <polyline fill="none" stroke="%s" stroke-width="%0.1fpt" %s points="',scolorname, width, pattern);
  2205. fprintf(fid,'%0.3f,%0.3f ',[xx;yy]);
  2206. fprintf(fid,'"/>\n');
  2207. end
  2208. else
  2209. parts=find(isnan(x)+isnan(y));
  2210. if parts(1)~=1
  2211. parts=[0 parts];
  2212. end
  2213. if parts(length(parts))~=length(x)
  2214. parts=[parts length(x)+1];
  2215. end
  2216. for j=1:(length(parts)-1)
  2217. xx=x((parts(j)+1):(parts(j+1)-1));
  2218. yy=y((parts(j)+1):(parts(j+1)-1));
  2219. if length(xx)~=0
  2220. fprintf(fid,' <polyline fill="none" stroke="%s" stroke-width="%0.1fpt" %s points="',scolorname, width, pattern);
  2221. fprintf(fid,'%0.3f,%0.3f ',[xx;yy]);
  2222. fprintf(fid,'"/>\n');
  2223. end
  2224. end
  2225. end
  2226. end
  2227. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2228. % create a circle
  2229. function circle2svg(fid,group,axpos,x,y,radius,markeredgecolorname,markerfacecolorname,width)
  2230. for j=1:length(x)
  2231. if ~(isnan(x(j)) | isnan(y(j)))
  2232. if ~strcmp(markeredgecolorname,'none') || ~strcmp(markerfacecolorname,'none')
  2233. fprintf(fid,'<circle cx="%0.3f" cy="%0.3f" r="%0.3f" fill="%s" stroke="%s" stroke-width="%0.1fpt" />\n',x(j),y(j),radius,markerfacecolorname,markeredgecolorname,width);
  2234. end
  2235. end
  2236. end
  2237. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2238. function control2svg(fid,id,ax,group,paperpos)
  2239. global PLOT2SVG_globals
  2240. set(ax,'Units','pixels');
  2241. pos=get(ax,'Position');
  2242. pict=getframe(id,pos);
  2243. if isempty(pict.colormap)
  2244. pict.colormap=colormap;
  2245. end
  2246. filename = [PLOT2SVG_globals.basefilename sprintf('%03d',PLOT2SVG_globals.figurenumber) '.' PLOT2SVG_globals.pixelfiletype];
  2247. PLOT2SVG_globals.figurenumber = PLOT2SVG_globals.figurenumber + 1;
  2248. if isempty(PLOT2SVG_globals.basefilepath)
  2249. current_path = pwd;
  2250. else
  2251. current_path = PLOT2SVG_globals.basefilepath;
  2252. end
  2253. if exist(fullfile(current_path,filename),'file')
  2254. lastwarn('');
  2255. delete(filename);
  2256. if strcmp(lastwarn,'File not found or permission denied.')
  2257. error('Cannot write image file. Make sure that no image is opened in an other program.')
  2258. end
  2259. end
  2260. imwrite(pict.cdata,fullfile(PLOT2SVG_globals.basefilepath,filename),PLOT2SVG_globals.pixelfiletype);
  2261. set(ax,'Units','normalized');
  2262. posNorm=get(ax,'Position');
  2263. posInches(1)=posNorm(1)*paperpos(3);
  2264. posInches(2)=posNorm(2)*paperpos(4);
  2265. posInches(3)=posNorm(3)*paperpos(3);
  2266. posInches(4)=posNorm(4)*paperpos(4);
  2267. lx = posInches(3);
  2268. ly = posInches(4);
  2269. pointsx = posInches(1);
  2270. pointsy = paperpos(4)-posInches(2)-posInches(4);
  2271. fprintf(fid,'<image x="%0.3f" y="%0.3f" width="%0.3f" height="%0.3f" image-rendering="optimizeSpeed" xlink:href="%s" />\n', pointsx, pointsy, lx, ly, filename);
  2272. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2273. % create a text in the axis frame
  2274. % the position of the text has to be adapted to the axis scaling
  2275. function text2svg(fid,group,axpos,paperpos,id,ax,projection)
  2276. global PLOT2SVG_globals;
  2277. originalTextUnits=get(id,'Units');
  2278. if PLOT2SVG_globals.octave
  2279. set(id,'Units','data');
  2280. else
  2281. set(id,'Units','Data');
  2282. end
  2283. textpos=get(id,'Position');
  2284. if PLOT2SVG_globals.octave
  2285. xlim = get(ax, 'XLim');
  2286. ylim = get(ax, 'YLim');
  2287. zlim = get(ax, 'ZLim');
  2288. if get(ax, 'XLabel') == id
  2289. textpos = textpos + [mean(xlim) ylim(1)-diff(ylim)./axpos(4)*0.06 0];
  2290. elseif get(ax, 'YLabel') == id
  2291. textpos = textpos + [xlim(1)-diff(xlim)./axpos(3)*0.06 mean(ylim) 0];
  2292. elseif get(ax, 'ZLabel') == id
  2293. if projection.xyplane
  2294. return;
  2295. end
  2296. textpos = textpos + [xlim(1)-diff(xlim)./axpos(3)*0.06 0 mean(zlim)];
  2297. elseif get(ax, 'Title') == id
  2298. textpos = textpos + [mean(xlim) ylim(2)+diff(ylim)./axpos(4)*0.01 0];
  2299. end
  2300. end
  2301. textfontsize=get(id,'FontSize');
  2302. fontsize=convertunit(get(id,'FontSize'),get(id,'FontUnits'),'points'); % convert fontsize to inches
  2303. paperposOriginal=get(gcf,'Position');
  2304. font_color=searchcolor(id,get(id,'Color'));
  2305. if strcmp(get(ax,'XScale'),'log')
  2306. textpos(1) = log10(textpos(1));
  2307. end
  2308. if strcmp(get(ax,'YScale'),'log')
  2309. textpos(2) = log10(textpos(2));
  2310. end
  2311. if strcmp(get(ax,'ZScale'),'log')
  2312. textpos(3) = log10(textpos(3));
  2313. end
  2314. [x,y,z] = project(textpos(1),textpos(2),textpos(3),projection);
  2315. x = (x*axpos(3)+axpos(1))*paperpos(3);
  2316. y = (1-(y*axpos(4)+axpos(2)))*paperpos(4);
  2317. textvalign=get(id,'VerticalAlignment');
  2318. textalign=get(id,'HorizontalAlignment');
  2319. texttext=get(id,'String');
  2320. textrot=get(id,'Rotation');
  2321. lines=max(size(get(id,'String'),1),1);
  2322. if size(texttext,2)~=0
  2323. j=1;
  2324. for i=0:1:(lines-1)
  2325. if iscell(texttext)
  2326. label2svg(fid,group,axpos,id,x,y+i*(fontsize*1.25*1.2),convertString(texttext{j}),textalign,textrot,textvalign,lines,paperpos,font_color,0)
  2327. else
  2328. label2svg(fid,group,axpos,id,x,y+i*(fontsize*1.25*1.2),convertString(texttext(j,:)),textalign,textrot,textvalign,lines,paperpos,font_color,0)
  2329. end
  2330. j=j+1;
  2331. end
  2332. else
  2333. label2svg(fid,group,axpos,id,x,y,'',textalign,textrot,textvalign,lines,paperpos,font_color,0)
  2334. end
  2335. set(id,'Units',originalTextUnits);
  2336. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2337. % adds the exponents to the axis thickmarks if needed
  2338. % MATLAB itself offers no information about this exponent scaling
  2339. % the exponent have therefore to be extracted from the thickmarks
  2340. function exponent2svg(fid,group,axpos,paperpos,ax)
  2341. global PLOT2SVG_globals
  2342. if strcmp(get(ax,'XTickLabelMode'),'auto') && strcmp(get(ax,'XScale'),'linear')
  2343. fontsize=convertunit(get(ax,'FontSize'),get(ax,'FontUnits'),'points'); % convert fontsize to inches
  2344. font_color=searchcolor(ax,get(ax,'XColor'));
  2345. if PLOT2SVG_globals.octave
  2346. % Octave stores XTickLabel in a cell array, which does not work nicely with str2num. --Jakob Malm
  2347. axlabelx = get(ax, 'XTickLabel');
  2348. numlabels = zeros(length(axlabelx), 1);
  2349. for ix = 1:length (axlabelx)
  2350. numlabels(ix) = str2num(axlabelx{ix});
  2351. end
  2352. else
  2353. numlabels = str2num(get(ax,'XTickLabel'));
  2354. end
  2355. labelpos = get(ax,'XTick');
  2356. numlabels = numlabels(:);
  2357. labelpos = labelpos(:);
  2358. indexnz = find(labelpos ~= 0);
  2359. if (~isempty(indexnz) && ~isempty(numlabels))
  2360. ratio=numlabels(indexnz)./labelpos(indexnz);
  2361. if round(log10(ratio(1))) ~= 0
  2362. exptext = sprintf('&#215; 10<tspan font-size="%0.1fpt" dy="%0.1fpt">%g</tspan>', 0.7*fontsize, -0.7*fontsize,-log10(ratio(1)));
  2363. label2svg(fid,group,axpos,ax,(axpos(1)+axpos(3))*paperpos(3),(1-axpos(2))*paperpos(4)+3*fontsize,exptext,'right',0,'top',1,paperpos,font_color,0)
  2364. end
  2365. end
  2366. end
  2367. if strcmp(get(ax,'YTickLabelMode'),'auto') && strcmp(get(ax,'YScale'),'linear')
  2368. fontsize=convertunit(get(ax,'FontSize'),get(ax,'FontUnits'),'points');
  2369. font_color=searchcolor(ax,get(ax,'YColor'));
  2370. if PLOT2SVG_globals.octave
  2371. % Octave stores YTickLabel in a cell array, which does not work nicely with str2num. --Jakob Malm
  2372. axlabely = get(ax, 'YTickLabel');
  2373. numlabels = zeros(length(axlabely), 1);
  2374. for ix = 1:length(axlabely)
  2375. numlabels(ix) = str2num(axlabely{ix});
  2376. end
  2377. else
  2378. numlabels = str2num(get(ax,'YTickLabel'));
  2379. end
  2380. labelpos = get(ax,'YTick');
  2381. numlabels = numlabels(:);
  2382. labelpos = labelpos(:);
  2383. indexnz = find(labelpos ~= 0);
  2384. if (~isempty(indexnz) && ~isempty(numlabels))
  2385. ratio = numlabels(indexnz)./labelpos(indexnz);
  2386. if round(log10(ratio(1))) ~= 0
  2387. exptext = sprintf('&#215; 10<tspan font-size="%0.1fpt" dy="%0.1fpt">%g</tspan>',0.7*fontsize,-0.7*fontsize,-log10(ratio(1)));
  2388. label2svg(fid,group,axpos,ax,axpos(1)*paperpos(3),(1-(axpos(2)+axpos(4)))*paperpos(4)-0.5*fontsize,exptext,'left',0,'bottom',1,paperpos,font_color,0)
  2389. end
  2390. end
  2391. end
  2392. if strcmp(get(ax,'ZTickLabelMode'),'auto') && strcmp(get(ax,'ZScale'),'linear')
  2393. fontsize=convertunit(get(ax,'FontSize'),get(ax,'FontUnits'),'points');
  2394. font_color=searchcolor(ax,get(ax,'ZColor'));
  2395. if PLOT2SVG_globals.octave
  2396. % Octave stores ZTickLabel in a cell array, which does not work nicely with str2num. --Jakob Malm
  2397. axlabelz = get (ax, 'ZTickLabel');
  2398. numlabels = zeros(length(axlabelz), 1);
  2399. for ix = 1:length(axlabelz)
  2400. numlabels(ix) = str2num(axlabelz{ix});
  2401. end
  2402. else
  2403. numlabels = str2num(get(ax,'ZTickLabel'));
  2404. end
  2405. labelpos = get(ax,'ZTick');
  2406. numlabels = numlabels(:);
  2407. labelpos = labelpos(:);
  2408. indexnz = find(labelpos ~= 0);
  2409. if (~isempty(indexnz) && ~isempty(numlabels))
  2410. ratio = numlabels(indexnz)./labelpos(indexnz);
  2411. if round(log10(ratio(1))) ~= 0
  2412. exptext = sprintf('&#215; 10<tspan font-size="%0.1fpt" dy="%0.1fpt">%g</tspan>',0.7*fontsize,-0.7*fontsize,-log10(ratio(1)));
  2413. label2svg(fid,group,axpos,ax,axpos(1)*paperpos(3),(1-(axpos(2)+axpos(4)))*paperpos(4)-0.5*fontsize,exptext,'left',0,'top',1,paperpos,font_color,0)
  2414. end
  2415. end
  2416. end
  2417. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2418. % create a label in the figure
  2419. % former versions of FrameMaker supported the commands FDY and FDX to shift the text
  2420. % this commands were replaced by a shift parameter that is normed by the font size
  2421. function label2svg(fid,group,axpos,id,x,y,tex,align,angle,valign,lines,paperpos,font_color,exponent)
  2422. if isempty(tex)
  2423. return;
  2424. end
  2425. textfontname=get(id,'FontName');
  2426. if strcmp(textfontname, '*')
  2427. textfontname = 'Arial';
  2428. end
  2429. set(id,'FontUnits','points');
  2430. textfontsize=get(id,'FontSize');
  2431. if isfield(get(id),'Interpreter')
  2432. if strcmp(get(id,'Interpreter'),'tex')
  2433. latex=1;
  2434. elseif strcmp(get(id,'Interpreter'),'latex')
  2435. latex=1;
  2436. else
  2437. latex=0;
  2438. end
  2439. else
  2440. latex=1;
  2441. end
  2442. fontsize=convertunit(get(id,'FontSize'),get(id,'FontUnits'),'points'); % convert fontsize to inches
  2443. paperposOriginal=get(gcf,'Position');
  2444. fontsize=fontsize*paperpos(4)/paperposOriginal(4);
  2445. textfontsize=textfontsize*paperpos(4)/paperposOriginal(4);
  2446. fontweight = get(id,'FontWeight');
  2447. switch lower(fontweight)
  2448. case 'bold', fweight = ' font-weight="bold"';
  2449. case 'light', fweight = ' font-weight="lighter"';
  2450. case 'demi', fweight = ' font-weight="lighter"';
  2451. otherwise, fweight = ''; % default 'normal'
  2452. end
  2453. fontangle = get(id,'FontAngle');
  2454. switch lower(fontangle)
  2455. case 'italic', fangle = ' font-style="italic"';
  2456. case 'oblique', fangle = ' font-style="oblique"';
  2457. otherwise, fangle = ''; % default 'normal'
  2458. end
  2459. % Note: The attribute 'alignment-baseline' cannot be used as it is often
  2460. % badly supported. Therfore, we use shifts.
  2461. switch lower(valign)
  2462. case 'top',shift=fontsize*1.18;
  2463. case 'cap',shift=fontsize*0.95;
  2464. case 'middle',shift = -((lines-1)/2*fontsize*1.25*1.2) + fontsize * 0.45;
  2465. case 'bottom',shift = -((lines-1)*fontsize*1.25*1.2) + fontsize * -0.25;
  2466. otherwise,shift=0;
  2467. end
  2468. switch lower(align)
  2469. case 'right', anchor = 'end';
  2470. case 'center',anchor = 'middle';
  2471. otherwise,anchor = 'start';
  2472. end
  2473. if iscellstr(tex)
  2474. tex = strvcat(tex);
  2475. elseif ~ ischar(tex)
  2476. error('Invalid character type');
  2477. end
  2478. if latex==1
  2479. tex=strrep(tex,'$','');
  2480. %if ~exponent
  2481. % try
  2482. % tex = texlabel(tex);
  2483. % catch
  2484. % fprintf(' Warning: Error during conversion to a latex string.');
  2485. % end
  2486. %end
  2487. tex=strrep(tex,'\alpha','{&#945;}');
  2488. tex=strrep(tex,'\beta','{&#946;}');
  2489. tex=strrep(tex,'\gamma','{&#947;}');
  2490. tex=strrep(tex,'\delta','{&#948;}');
  2491. tex=strrep(tex,'\epsilon','{&#949;}');
  2492. tex=strrep(tex,'\zeta','{&#950;}');
  2493. tex=strrep(tex,'\eta','{&#951;}');
  2494. tex=strrep(tex,'\theta','{&#952;}');
  2495. tex=strrep(tex,'\vartheta','{&#977;}');
  2496. tex=strrep(tex,'\iota','{&#953;}');
  2497. tex=strrep(tex,'\kappa','{&#954;}');
  2498. tex=strrep(tex,'\lambda','{&#955;}');
  2499. tex=strrep(tex,'\mu','{&#181;}');
  2500. tex=strrep(tex,'\nu','{&#957;}');
  2501. tex=strrep(tex,'\xi','{&#958;}');
  2502. tex=strrep(tex,'\pi','{&#960;}');
  2503. tex=strrep(tex,'\rho','{&#961;}');
  2504. tex=strrep(tex,'\sigma','{&#963;}');
  2505. tex=strrep(tex,'\varsigma','{&#962;}');
  2506. tex=strrep(tex,'\tau','{&#964;}');
  2507. tex=strrep(tex,'\upsilon','{&#965;}');
  2508. tex=strrep(tex,'\phi','{&#966;}');
  2509. tex=strrep(tex,'\chi','{&#967;}');
  2510. tex=strrep(tex,'\psi','{&#968;}');
  2511. tex=strrep(tex,'\omega','{&#969;}');
  2512. tex=strrep(tex,'\Gamma','{&#915;}');
  2513. tex=strrep(tex,'\Delta','{&#916;}');
  2514. tex=strrep(tex,'\Theta','{&#920;}');
  2515. tex=strrep(tex,'\Lambda','{&#923;}');
  2516. tex=strrep(tex,'\Xi','{&#926;}');
  2517. tex=strrep(tex,'\Pi','{&#928;}');
  2518. tex=strrep(tex,'\Sigma','{&#931;}');
  2519. tex=strrep(tex,'\Tau','{&#932;}');
  2520. tex=strrep(tex,'\Upsilon','{&#933;}');
  2521. tex=strrep(tex,'\Phi','{&#934;}');
  2522. tex=strrep(tex,'\Psi','{&#936;}');
  2523. tex=strrep(tex,'\Omega','{&#937;}');
  2524. tex=strrep(tex,'\infty','{&#8734;}');
  2525. tex=strrep(tex,'\pm','{&#177;}');
  2526. tex=strrep(tex,'\Im','{&#8465;}');
  2527. tex=strrep(tex,'\Re','{&#8476;}');
  2528. tex=strrep(tex,'\approx','{&#8773;}');
  2529. tex=strrep(tex,'\leq','{&#8804;}');
  2530. tex=strrep(tex,'\geq','{&#8805;}');
  2531. tex=strrep(tex,'\times','{&#215;}');
  2532. tex=strrep(tex,'\leftrightarrow','{&#8596;}');
  2533. tex=strrep(tex,'\leftarrow','{&#8592;}');
  2534. tex=strrep(tex,'\uparrow','{&#8593;}');
  2535. tex=strrep(tex,'\rightarrow','{&#8594;}');
  2536. tex=strrep(tex,'\downarrow','{&#8595;}');
  2537. tex=strrep(tex,'\circ','{&#186;}');
  2538. tex=strrep(tex,'\propto','{&#8733;}');
  2539. tex=strrep(tex,'\partial','{&#8706;}');
  2540. tex=strrep(tex,'\bullet','{&#8226;}');
  2541. tex=strrep(tex,'\div','{&#247;}');
  2542. tex=strrep(tex,'\sum','{&#8721;}');
  2543. tex=strrep(tex,'\ast','{&#8727;}');
  2544. tex=strrep(tex,'\sqrt','{&#8730;}');
  2545. tex=strrep(tex,'\angle','{&#8736;}');
  2546. tex=strrep(tex,'\wedge','{&#8743;}');
  2547. tex=strrep(tex,'\land','{&#8743;}');
  2548. tex=strrep(tex,'\vee','{&#8744;}');
  2549. tex=strrep(tex,'\lor','{&#8744;}');
  2550. tex=strrep(tex,'\cap','{&#8745;}');
  2551. tex=strrep(tex,'\cup','{&#8746;}');
  2552. tex=strrep(tex,'\int','{&#8747;}');
  2553. %&there4;&#8756;
  2554. tex=strrep(tex,'\sim','{&#8764;}');
  2555. tex=strrep(tex,'\forall','{&#8704;}');
  2556. tex=strrep(tex,'\partial','{&#8706;}');
  2557. tex=strrep(tex,'\exists','{&#8707;}');
  2558. tex=strrep(tex,'\emptyset','{&#8709;}');
  2559. tex=strrep(tex,'\nabla','{&#8711;}');
  2560. tex=strrep(tex,'\in','{&#8712;}');
  2561. tex=strrep(tex,'\notin','{&#8713;}');
  2562. tex=strrep(tex,'\ni','{&#8715;}');
  2563. tex=strrep(tex,'\prod','{&#8719;}');
  2564. tex=strrep(tex,'\cong','{&#8773;}');
  2565. tex=strrep(tex,'\approx','{&#8776;}');
  2566. tex=strrep(tex,'\neq','{&#8800;}');
  2567. tex=strrep(tex,'\equiv','{&#8801;}');
  2568. tex=strrep(tex,'\leq','{&#8804;}');
  2569. tex=strrep(tex,'\geq','{&#8805;}');
  2570. tex=strrep(tex,'\subset','{&#8834;}');
  2571. tex=strrep(tex,'\supset','{&#8835;}');
  2572. %&nsub;&#8836;
  2573. tex=strrep(tex,'\subseteq','{&#8838;}');
  2574. tex=strrep(tex,'\supseteq','{&#8839;}');
  2575. tex=strrep(tex,'\oplus','{&#8853;}');
  2576. tex=strrep(tex,'\otimes','{&#8855;}');
  2577. tex=strrep(tex,'\bot','{&#8869;}');
  2578. tex=strrep(tex,'\cdot','{&#8901;}');
  2579. tex=strrep(tex,'\bullet','{&#8226;}');
  2580. tex=strrep(tex,'\ldots','{&#8230;}');
  2581. tex=strrep(tex,'\prime','{&#8242;}');
  2582. % &#8243; double prime
  2583. % &#8254; oline
  2584. tex=strrep(tex,'\\','{&#92;}');
  2585. tex=strrep(tex,'\{','{&#123;}');
  2586. tex=strrep(tex,'\}','{&#125;}');
  2587. tex=strrep(tex,'\_','{&#95;}');
  2588. tex=strrep(tex,'\^','{&#94;}');
  2589. %fprintf('%s\n', tex);
  2590. tex=latex2svg(tex, textfontname, textfontsize, 0);
  2591. end
  2592. if isempty(tex)
  2593. return;
  2594. end
  2595. if exponent
  2596. tex=sprintf('10<tspan font-size="%0.1fpt" dy="%0.1fpt">%s</tspan>', 0.7*textfontsize, -0.7*textfontsize, tex);
  2597. shift = shift + 0.4*fontsize; % Small correction to make it look nicer
  2598. end
  2599. % Note: Obviously, Matlab is using font sizes that are rounded to decimal
  2600. % pt sizes. This may cause problems for very small figures. But we have to
  2601. % follow due to the background size.
  2602. %fprintf('%s\n', tex);
  2603. fprintf(fid,' <g transform="translate(%0.3f,%0.3f)">\n', x - shift * sin(-angle/180*pi), y + shift * cos(-angle/180*pi));
  2604. fprintf(fid,' <g transform="rotate(%0.1f)">\n',-angle);
  2605. fprintf(fid,' <text x="%0.3f" y="%0.3f" font-family="%s" text-anchor="%s" font-size="%0.0fpt"%s%s fill="%s" >', 0, 0, textfontname, anchor, textfontsize, fweight, fangle, font_color);
  2606. fprintf(fid,'%s',tex);
  2607. fprintf(fid,'</text>\n');
  2608. fprintf(fid,' </g>\n');
  2609. fprintf(fid,' </g>\n');
  2610. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2611. % converts LATEX strings into SVG strings
  2612. function returnvalue = latex2svg(StringText, font, size, style)
  2613. returnvalue = StringText;
  2614. try
  2615. if ~isempty(StringText)
  2616. bracket = find(StringText == '{' | StringText == '}');
  2617. bracketCounter = zeros(1,length(StringText));
  2618. bracketCounter(StringText == '{') = 1;
  2619. bracketCounter(StringText == '}') = -1;
  2620. bracketCounter = cumsum(bracketCounter);
  2621. if bracketCounter(end) ~= 0
  2622. fprintf(['Warning: Number of open and closed braces is not equal. Latex string ''' StringText ''' will not be converted.\n']);
  2623. elseif any(bracketCounter < 0)
  2624. fprintf(['Warning: Found a closed brace without a previously opened brace. Latex string ''' StringText ''' will not be converted.\n']);
  2625. else
  2626. if isempty(bracket)
  2627. if ~isempty(find(StringText == '^' | StringText == '_' | StringText == '\' ))
  2628. returnvalue = ['<tspan>' singleLatex2svg(StringText, size) '</tspan>'];
  2629. % Clean up empty tspan elements
  2630. % More could be done here, but with huge effort to make it
  2631. % match all special cases.
  2632. returnvalue = strrep(returnvalue, '></tspan><tspan>', '>');
  2633. else
  2634. returnvalue = StringText;
  2635. end
  2636. else
  2637. returnvalue = '<tspan>';
  2638. lastValidCharacter = 1;
  2639. localSize = size;
  2640. restoreOffset = [];
  2641. restoreSize = [];
  2642. for i = 1:length(bracket)
  2643. lastValidCharacterOffset = 1;
  2644. if StringText(bracket(i)) == '{'
  2645. % Found '{'
  2646. removeCharacters = 1;
  2647. localOffset = 0;
  2648. restoreOffset(bracketCounter(bracket(i))) = 0;
  2649. restoreSize(bracketCounter(bracket(i))) = localSize;
  2650. if (bracket(i) > 1)
  2651. if StringText(bracket(i) - 1) == '_'
  2652. localOffset = -0.4 * localSize;
  2653. localSize = 0.7 * localSize;
  2654. restoreOffset(bracketCounter(bracket(i))) = -localOffset;
  2655. removeCharacters = 2;
  2656. elseif StringText(bracket(i) - 1) == '^'
  2657. localOffset = 0.5 * localSize;
  2658. localSize = 0.7 * localSize;
  2659. restoreOffset(bracketCounter(bracket(i))) = -localOffset;
  2660. removeCharacters = 2;
  2661. end
  2662. end
  2663. returnvalue = [returnvalue singleLatex2svg(StringText(lastValidCharacter:bracket(i) - removeCharacters), restoreSize(bracketCounter(bracket(i)))) '</tspan><tspan'];
  2664. if localOffset ~= 0
  2665. returnvalue = [returnvalue ' dy="' num2str(-localOffset, '%0.1f') 'pt"'];
  2666. end
  2667. if localSize ~= restoreSize(bracketCounter(bracket(i)))
  2668. returnvalue = [returnvalue ' font-size="' num2str(localSize, '%0.0f') 'pt"'];
  2669. end
  2670. returnvalue = [returnvalue '>'];
  2671. else
  2672. % Found '}'
  2673. returnvalue = [returnvalue singleLatex2svg(StringText(lastValidCharacter:bracket(i) - 1), localSize) '</tspan><tspan'];
  2674. if restoreOffset(bracketCounter(bracket(i) - 1)) ~= 0
  2675. returnvalue = [returnvalue ' dy="' num2str(-restoreOffset(bracketCounter(bracket(i) - 1)), '%0.1f') 'pt"'];
  2676. end
  2677. if restoreSize(bracketCounter(bracket(i) - 1)) ~= localSize
  2678. localSize = restoreSize(bracketCounter(bracket(i) - 1));
  2679. returnvalue = [returnvalue ' font-size="' num2str(localSize, '%0.0f') 'pt"'];
  2680. end
  2681. returnvalue = [returnvalue '>'];
  2682. end
  2683. lastValidCharacter = bracket(i) + lastValidCharacterOffset;
  2684. end
  2685. if lastValidCharacter <= length(StringText)
  2686. returnvalue = [returnvalue singleLatex2svg(StringText(lastValidCharacter:end), localSize)];
  2687. end
  2688. returnvalue = [returnvalue '</tspan>'];
  2689. % Clean up empty tspan elements
  2690. % More could be done here, but with huge effort to make it
  2691. % match all special cases.
  2692. returnvalue = strrep(returnvalue, '></tspan><tspan>', '>');
  2693. end
  2694. end
  2695. end
  2696. catch
  2697. fprintf(['Warning: Error ''' lasterr ''' occurred during conversion. Latex string ''' StringText ''' will not be converted.\n']);
  2698. end
  2699. function StringText = singleLatex2svg(StringText, size)
  2700. index = find(StringText == '_' | StringText == '^');
  2701. if ~isempty(index)
  2702. if index(end) == length(StringText)
  2703. % Remove orphan '_' or '^'
  2704. index = index(1:end-1);
  2705. end
  2706. for i = length(index):-1:1
  2707. if StringText(index(i)) == '_'
  2708. localOffset = 0.4 * size;
  2709. localSize = 0.7 * size;
  2710. StringText = [StringText(1:index(i)-1) ...
  2711. '</tspan><tspan dy="' num2str(localOffset, '%0.1f') 'pt" font-size="' num2str(localSize, '%0.0f') 'pt">' ...
  2712. StringText(index(i)+1) ...
  2713. '</tspan><tspan dy="' num2str(-localOffset, '%0.1f') 'pt" font-size="' num2str(size, '%0.0f') 'pt">' ...
  2714. StringText(index(i)+2:end)];
  2715. else
  2716. localOffset = 0.5 * size;
  2717. localSize = 0.7 * size;
  2718. StringText = [StringText(1:index(i)-1) ...
  2719. '</tspan><tspan dy="' num2str(-localOffset, '%0.1f') 'pt" font-size="' num2str(localSize, '%0.0f') 'pt">' ...
  2720. StringText(index(i)+1) ...
  2721. '</tspan><tspan dy="' num2str(localOffset, '%0.1f') 'pt" font-size="' num2str(size, '%0.0f') 'pt">' ...
  2722. StringText(index(i)+2:end)];
  2723. end
  2724. end
  2725. end
  2726. if ~isempty(strfind(StringText, '\bf'))
  2727. StringText = strrep(StringText, '\bf', '</tspan><tspan font-weight="bold">');
  2728. end
  2729. if ~isempty(strfind(StringText, '\it'))
  2730. StringText = strrep(StringText, '\it', '</tspan><tspan font-style="italic">');
  2731. end
  2732. if ~isempty(strfind(StringText, '\sl'))
  2733. StringText = strrep(StringText, '\sl', '</tspan><tspan font-style="oblique">');
  2734. end
  2735. if ~isempty(strfind(StringText, '\rm'))
  2736. StringText = strrep(StringText, '\rm', '</tspan><tspan font-style="normal" font-weight="normal">');
  2737. end
  2738. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2739. function name=searchcolor(id,value)
  2740. if ischar(value)
  2741. name = value;
  2742. else
  2743. name=sprintf('#%02x%02x%02x',fix(value(1)*255),fix(value(2)*255),fix(value(3)*255));
  2744. end
  2745. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2746. function rvalue = convertunit(value, from, to)
  2747. % From SVG 1.1. Specification:
  2748. % "1pt" equals "1.25px" (and therefore 1.25 user units)
  2749. % "1pc" equals "15px" (and therefore 15 user units)
  2750. % "1mm" would be "3.543307px" (3.543307 user units)
  2751. % "1cm" equals "35.43307px" (and therefore 35.43307 user units)
  2752. % "1in" equals "90px" (and therefore 90 user units)
  2753. switch lower(from) % convert from input unit to points
  2754. case 'pixels', rvalue = value * 0.8;
  2755. case 'points', rvalue = value;
  2756. case 'centimeters', rvalue = value / 2.54*72;
  2757. case 'inches', rvalue = value * 72; % 72 points = 1 inch
  2758. otherwise, error(['Unknown unit ' from '.']);
  2759. end
  2760. switch lower(to) % convert from points to specified unit
  2761. case 'pixels', rvalue = rvalue * 1.25;
  2762. case 'points'; % do nothing
  2763. case 'centimeters', rvalue = rvalue * 2.54 / 72;
  2764. case 'inches', rvalue = rvalue / 72; % 72 points = 1 inch
  2765. otherwise, error(['Unknown unit ' to '.']);
  2766. end
  2767. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2768. function strString=addBackSlash( strSlash)
  2769. % adds a backslash at the last position of the string (if not already there)
  2770. if ( strSlash(end) ~= filesep)
  2771. strString = [ strSlash filesep];
  2772. else
  2773. strString = strSlash;
  2774. end
  2775. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2776. function strExt=getFileExtension( strFileName)
  2777. % returns the file extension of a filename
  2778. [path, name, strExt] = fileparts( strFileName);
  2779. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2780. function StringText=convertString(StringText)
  2781. if iscell(StringText) % Octave stores some strings in cell arrays. --Jakob Malm
  2782. StringText = StringText{1};
  2783. end
  2784. if ~isempty(StringText)
  2785. StringText=strrep(StringText,'&','&amp;'); % Do not change sequence !!
  2786. StringText=strrep(StringText,'\\','\');
  2787. StringText=strrep(StringText,'<','&lt;');
  2788. StringText=strrep(StringText,'>','&gt;');
  2789. StringText=strrep(StringText,'"','&quot;');
  2790. % Workaround for Firefox and Inkscape
  2791. StringText=strrep(StringText,'°','°');
  2792. %StringText=strrep(StringText,'°','&deg;');
  2793. StringText=strrep(StringText,'ą','&plusmn;');
  2794. StringText=strrep(StringText,'ľ','&micro;');
  2795. StringText=strrep(StringText,'˛','&sup2;');
  2796. StringText=strrep(StringText,'ł','&sup3;');
  2797. StringText=strrep(StringText,'ź','&frac14;');
  2798. StringText=strrep(StringText,'˝','&frac12;');
  2799. StringText=strrep(StringText,'ž','&frac34;');
  2800. StringText=strrep(StringText,'Š','&copy;');
  2801. StringText=strrep(StringText,'Ž','&reg;');
  2802. if any(StringText > 190)
  2803. StringText=strrep(StringText,'ż','&#191;');
  2804. StringText=strrep(StringText,'Ŕ','&#192;');
  2805. StringText=strrep(StringText,'Á','&#193;');
  2806. StringText=strrep(StringText,'Â','&#194;');
  2807. StringText=strrep(StringText,'Ă','&#195;');
  2808. StringText=strrep(StringText,'Ä','&#196;');
  2809. StringText=strrep(StringText,'Ĺ','&#197;');
  2810. StringText=strrep(StringText,'Ć','&#198;');
  2811. StringText=strrep(StringText,'Ç','&#199;');
  2812. StringText=strrep(StringText,'Č','&#200;');
  2813. StringText=strrep(StringText,'É','&#201;');
  2814. StringText=strrep(StringText,'Ę','&#202;');
  2815. StringText=strrep(StringText,'Ë','&#203;');
  2816. StringText=strrep(StringText,'Ě','&#204;');
  2817. StringText=strrep(StringText,'Í','&#205;');
  2818. StringText=strrep(StringText,'Î','&#206;');
  2819. StringText=strrep(StringText,'Ď','&#207;');
  2820. StringText=strrep(StringText,'Đ','&#208;');
  2821. StringText=strrep(StringText,'Ń','&#209;');
  2822. StringText=strrep(StringText,'Ň','&#210;');
  2823. StringText=strrep(StringText,'Ó','&#211;');
  2824. StringText=strrep(StringText,'Ô','&#212;');
  2825. StringText=strrep(StringText,'Ő','&#213;');
  2826. StringText=strrep(StringText,'Ö','&#214;');
  2827. StringText=strrep(StringText,'×','&#215;');
  2828. StringText=strrep(StringText,'Ř','&#216;');
  2829. StringText=strrep(StringText,'Ů','&#217;');
  2830. StringText=strrep(StringText,'Ú','&#218;');
  2831. StringText=strrep(StringText,'Ű','&#219;');
  2832. StringText=strrep(StringText,'Ü','&#220;');
  2833. StringText=strrep(StringText,'Ý','&#221;');
  2834. StringText=strrep(StringText,'Ţ','&#222;');
  2835. StringText=strrep(StringText,'ß','&#223;');
  2836. StringText=strrep(StringText,'ŕ','&#224;');
  2837. StringText=strrep(StringText,'á','&#225;');
  2838. StringText=strrep(StringText,'â','&#226;');
  2839. StringText=strrep(StringText,'ă','&#227;');
  2840. StringText=strrep(StringText,'ä','&#228;');
  2841. StringText=strrep(StringText,'ĺ','&#229;');
  2842. StringText=strrep(StringText,'ć','&#230;');
  2843. StringText=strrep(StringText,'ç','&#231;');
  2844. StringText=strrep(StringText,'č','&#232;');
  2845. StringText=strrep(StringText,'é','&#233;');
  2846. StringText=strrep(StringText,'ę','&#234;');
  2847. StringText=strrep(StringText,'ë','&#235;');
  2848. StringText=strrep(StringText,'ě','&#236;');
  2849. StringText=strrep(StringText,'í','&#237;');
  2850. StringText=strrep(StringText,'î','&#238;');
  2851. StringText=strrep(StringText,'ď','&#239;');
  2852. StringText=strrep(StringText,'đ','&#240;');
  2853. StringText=strrep(StringText,'ń','&#241;');
  2854. StringText=strrep(StringText,'ň','&#242;');
  2855. StringText=strrep(StringText,'ó','&#243;');
  2856. StringText=strrep(StringText,'ô','&#244;');
  2857. StringText=strrep(StringText,'ő','&#245;');
  2858. StringText=strrep(StringText,'ö','&#246;');
  2859. StringText=strrep(StringText,'÷','&#247;');
  2860. StringText=strrep(StringText,'ř','&#248;');
  2861. StringText=strrep(StringText,'ů','&#249;');
  2862. StringText=strrep(StringText,'ú','&#250;');
  2863. StringText=strrep(StringText,'ű','&#251;');
  2864. StringText=strrep(StringText,'ü','&#252;');
  2865. StringText=strrep(StringText,'ý','&#253;');
  2866. StringText=strrep(StringText,'ţ','&#254;');
  2867. StringText=strrep(StringText,'˙','&#255;');
  2868. end
  2869. StringText=deblank(StringText);
  2870. end
  2871. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2872. function IdString = createId
  2873. global PLOT2SVG_globals
  2874. IdString = ['ID' sprintf('%06d',PLOT2SVG_globals.runningIdNumber)];
  2875. PLOT2SVG_globals.runningIdNumber = PLOT2SVG_globals.runningIdNumber + 1;
  2876. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2877. function [projection, edges] = get_projection(ax,id)
  2878. global PLOT2SVG_globals
  2879. xc = get(ax,'CameraTarget');
  2880. phi = get(ax,'CameraViewAngle');
  2881. vi = get(ax,'View');
  2882. xi = get(ax,'XLim');
  2883. yi = get(ax,'YLim');
  2884. zi = get(ax,'ZLim');
  2885. if strcmp(get(ax,'XScale'),'log')
  2886. if strcmp(get(ax,'XLimMode'),'manual') && any(get(ax,'XLim') == 0)
  2887. % Fix illegal scalings set by the user
  2888. % -> replace all 0 with automatic calculated values (child limits)
  2889. xlimM = get(ax,'XLim');
  2890. set(ax,'XLimMode','auto');
  2891. xlimA = get(ax,'XLim');
  2892. xlimM(xlimM == 0) = xlimA(xlimM == 0);
  2893. set(ax,'XLimMode','manual');
  2894. set(ax,'XLim', xlimM);
  2895. end
  2896. xi=log10(get(ax,'XLim'));
  2897. end
  2898. if strcmp(get(ax,'YScale'),'log')
  2899. if strcmp(get(ax,'YLimMode'),'manual') && any(get(ax,'YLim') == 0)
  2900. % Fix illegal scalings set by the user
  2901. % -> replace all 0 with automatic calculated values (child limits)
  2902. ylimM = get(ax,'YLim');
  2903. set(ax,'YLimMode','auto');
  2904. ylimA = get(ax,'YLim');
  2905. ylimM(ylimM == 0) = ylimA(ylimM == 0);
  2906. set(ax,'YLimMode','manual');
  2907. set(ax,'YLim', ylimM);
  2908. end
  2909. yi=log10(get(ax,'YLim'));
  2910. end
  2911. if strcmp(get(ax,'ZScale'),'log')
  2912. if strcmp(get(ax,'ZLimMode'),'manual') && any(get(ax,'ZLim') == 0)
  2913. % Fix illegal scalings set by the user
  2914. % -> replace all 0 with automatic calculated values (child limits)
  2915. zlimM = get(ax,'ZLim');
  2916. set(ax,'ZLimMode','auto');
  2917. zlimA = get(ax,'ZLim');
  2918. zlimM(zlimM == 0) = zlimA(zlimM == 0);
  2919. set(ax,'ZLimMode','manual');
  2920. set(ax,'ZLim', zlimM);
  2921. end
  2922. zi=log10(get(ax,'ZLim'));
  2923. end
  2924. projection.xi = xi;
  2925. projection.yi = yi;
  2926. projection.zi = zi;
  2927. projection.aspect_scaling = get(ax,'DataAspectRatio');
  2928. xc(1) = (xc(1) - xi(1))/(xi(2)-xi(1));
  2929. xc(2) = (xc(2) - yi(1))/(yi(2)-yi(1));
  2930. xc(3) = (xc(3) - zi(1))/(zi(2)-zi(1));
  2931. x = [xi(1) xi(2) xi(1) xi(2) xi(1) xi(2) xi(1) xi(2)]/projection.aspect_scaling(1);
  2932. y = [yi(1) yi(1) yi(2) yi(2) yi(1) yi(1) yi(2) yi(2)]/projection.aspect_scaling(2);
  2933. z = [zi(1) zi(1) zi(1) zi(1) zi(2) zi(2) zi(2) zi(2)]/projection.aspect_scaling(3);
  2934. if PLOT2SVG_globals.octave
  2935. projection.A = get(ax,'x_ViewTransform');
  2936. projection.A(3,:) = -projection.A(3,:);
  2937. projection.A(1:3,4) = 0;
  2938. else
  2939. if strcmp(get(ax,'Projection'),'orthographic')
  2940. projection.A = viewmtx(vi(1),vi(2));
  2941. else
  2942. projection.A = viewmtx(vi(1),vi(2),phi,xc);
  2943. end
  2944. end
  2945. if (vi(1) == 0) && (mod(vi(2),90) == 0)
  2946. projection.xyplane = true;
  2947. else
  2948. projection.xyplane = false;
  2949. end
  2950. axpos = get(ax,'Position');
  2951. figpos = get(id,'Position');
  2952. [m,n] = size(x);
  2953. x4d = [x(:),y(:),z(:),ones(m*n,1)]';
  2954. x2d = projection.A*x4d;
  2955. x2 = zeros(m,n); y2 = zeros(m,n); z2 = zeros(m,n);
  2956. x2(:) = x2d(1,:)./x2d(4,:);
  2957. y2(:) = x2d(2,:)./x2d(4,:);
  2958. projection.ax = ax;
  2959. projection.xrange = max(x2) - min(x2);
  2960. projection.yrange = max(y2) - min(y2);
  2961. projection.xoffset = (max(x2) + min(x2))/2;
  2962. projection.yoffset = (max(y2) + min(y2))/2;
  2963. if (strcmp(get(ax,'PlotBoxAspectRatioMode'),'manual') || strcmp(get(ax,'DataAspectRatioMode'),'manual'))
  2964. if (projection.xrange*axpos(4)*figpos(4) < projection.yrange*axpos(3)*figpos(3))
  2965. projection.xrange = projection.yrange*axpos(3)*figpos(3)/axpos(4)/figpos(4);
  2966. else
  2967. projection.yrange = projection.xrange*axpos(4)*figpos(4)/axpos(3)/figpos(3);
  2968. end
  2969. end
  2970. x2(:) = (x2d(1,:)./x2d(4,:) - projection.xoffset)/projection.xrange + 0.5;
  2971. y2(:) = (x2d(2,:)./x2d(4,:) - projection.yoffset)/projection.yrange + 0.5;
  2972. z2(:) = x2d(3,:);
  2973. edges = [x2; y2; z2];
  2974. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2975. function [x2,y2,z2] = project(x,y,z,projection)
  2976. [m,n] = size(x);
  2977. if strcmp(get(projection.ax,'XDir'),'reverse')
  2978. xi = projection.xi;
  2979. x = (1 - (x - xi(1)) / (xi(2) - xi(1))) * (xi(2) - xi(1)) + xi(1);
  2980. end
  2981. if strcmp(get(projection.ax,'YDir'),'reverse')
  2982. yi = projection.yi;
  2983. y = (1 - (y - yi(1)) / (yi(2) - yi(1))) * (yi(2) - yi(1)) + yi(1);
  2984. end
  2985. x4d = [x(:)/projection.aspect_scaling(1), y(:)/projection.aspect_scaling(2), z(:)/projection.aspect_scaling(3), ones(m*n,1)]';
  2986. x2d = projection.A*x4d;
  2987. x2 = zeros(m,n); y2 = zeros(m,n); z2 = zeros(m,n);
  2988. x2(:) = (x2d(1,:)./x2d(4,:) - projection.xoffset)/projection.xrange + 0.5;
  2989. y2(:) = (x2d(2,:)./x2d(4,:) - projection.yoffset)/projection.yrange + 0.5;
  2990. z2(:) = x2d(3,:);
  2991. %x = [0 1 0 1 0 1 0 1];
  2992. %y = [0 0 1 1 0 0 1 1];
  2993. %z = [0 0 0 0 1 1 1 1];
  2994. function [f, v, fvc, fva] = surface2patch(s)
  2995. x = get(s, 'xdata');
  2996. y = get(s, 'ydata');
  2997. z = get(s, 'zdata');
  2998. c = get(s, 'cdata');
  2999. a = get(s, 'AlphaData');
  3000. if ~isempty(x) & ~isequal(size(x),size(z))
  3001. x = repmat(x(:)',size(z,1),1);
  3002. end
  3003. if ~isempty(y) & ~isequal(size(y),size(z))
  3004. y = repmat(y(:),1,size(z,2));
  3005. end
  3006. [m n]= size(z);
  3007. if isempty(x)
  3008. [x y] = meshgrid(1:n, 1:m);
  3009. end
  3010. [cm cn cp] = size(c);
  3011. [am an ap] = size(a);
  3012. %if cm==(m-1) & cn==(n-1)
  3013. % cmode = 'f';
  3014. %elseif cm==m & cn==n
  3015. % cmode = 'v';
  3016. %else
  3017. % cmode = '';
  3018. %end
  3019. v = [x(:) y(:) z(:)];
  3020. q = [1:m*n-m-1]';
  3021. q(m:m:end) = [];
  3022. fvc = reshape(c, [cm*cn cp]);
  3023. fva = reshape(a, [am*an ap]);
  3024. f = [q q+m q+m+1 q+1];