function varargout = plot2svg(param1,id,pixelfiletype) % Matlab to SVG converter % Prelinary version supporting 3D plots as well % % Usage: plot2svg(filename,graphic handle,pixelfiletype) % optional optional optional % or % % plot2svg(figuresize,graphic handle,pixelfiletype) % optional optional optional % % pixelfiletype = 'png' (default), 'jpg' % % Juerg Schwizer 23-Oct-2005 % See http://www.zhinst.com/blogs/schwizer/ to get more informations % 07.06.2005 - Bugfix axxindex (Index exceeds matrix dimensions) % 19.09.2005 - Added possibility to select output format of pixel graphics % 23.10.2005 - Bugfix cell array strings (added by Bill) % Handling of 'hggroups' and improved grouping of objects % Improved handling of pixel images (indexed and true color pictures) % 23.10.2005 - Switched default pixelfromat to 'png' % 07.11.2005 - Added handling of hidden axes for annotations (added by Bill) % 03.12.2005 - Bugfix of viewBox to make Firefox 1.5 working % 04.12.2005 - Improved handling of exponent values for log-plots % Improved markers % 09.12.2005 - Bugfix '<' '>' '?' '"' % 22.12.2005 - Implementation of preliminary 3D version % Clipping % Minor tick marks % 22.01.2005 - Removed unused 'end' % 29.10.2006 - Bugfix '°','±','µ','²','³','¼''½','¾','©''®' % 17-04-2007 - Bugfix 'projection' in hggroup and hgtransform % 27-01-2008 - Added Octave functionality (thanks to Jakob Malm) % Bugfixe cdatamapping (thanks to Tom) % Bugfix image data writing (thanks to Tom) % Patches includes now markers as well (needed for 'scatter' % plots (thanks to Phil) % 04-02-2008 - Bugfix markers for Octave (thanks to Jakob Malm) % 30-12-2008 - Bugfix image scaling and orientation % Bugfix correct backslash (thanks to Jason Merril) % 20-06-2009 - Improvment of image handling (still some remaining issues) % Fix for -. line style (thanks to Ritesh Sood) % 28-06-2009 - Improved depth sorting for patches and surface % - Bugfix patches % - Bugfix 3D axis handling % 11-07-2009 - Support of FontWeight and FontAngle properties % - Improved markers (polygon instead of polyline for closed markers) % - Added character encoding entry to be fully SVG 1.1 conform % 13-07-2009 - Support of rectangle for 2D % - Added preliminary support for SVG filters % - Added preliminary support for clipping with pathes % - Added preliminary support for turning axis tickmarks % 18-07-2009 - Line style scaling with line width (will not match with png % output) % - Small optimizations for the text base line % - Bugfix text rotation versus shift % - Added more SVG filters % - Added checks for filter strings % 21-07-2009 - Improved bounding box calculation for filters % - Bugfixes for text size / line distance % - Support of background box for text % - Correct bounding box for text objects % 31-07-2009 - Improved support of filters % - Experimental support of animations % 16-08-2009 - Argument checks for filters % - Rework of latex string handling % - 'sub' and 'super' workaround for Firefox and Inkscape % 31-10-2009 - Bugfix for log axes (missing minor grid for some special % cases) % 24-01-2010 - Bugfix nomy line #1102 (thanks to Pooya Jannaty) % 17-02-2010 - Bugfix minor tickmarks for log axis scaling (thanks to % Harke Pera) % - Added more lex symbols % 06-03-2010 - Automatic correction of illegal axis scalings by the user % (thanks to Juergen) % - Renamed plot2svg_beta to plot2svg % 12-04-2010 - Improved Octave compatibility % 05-05-2010 - Bugfix for ticklabels outside of the axis limits (thanks to % Ben Scandella) % 30-10-2010 - Improved handling of empty cells for labels (thanks to % Constantine) % - Improved HTML character coding (thanks to David Mack) % - Bugfix for last ')' (thanks to Jonathon Harding and Benjamin) % - Enabled scatter plots using hggroups % - Closing patches if they do not contain NaNs % 10-11-2010 - Support of the 'Layer' keyword to but the grid on top of % of the other axis content using 'top' (Many thanks to Justin % Ashmall) % - Tiny optimization of the grid display at axis borders % 25-08-2011 - Fix for degree character (thanks to Manes Recheis) % - Fix for problems with dash-arrays in Inkscape (thanks to % Rüdiger Stirnberg) % - Modified shape of driangles (thanks to Rüdiger Stirnberg) % 22-10-2011 - Removed versn as return value of function fileparts (thanks % to Andrew Scott) % - Fix for images (thanks to Roeland) % 20-05-2012 - Added some security checks for empty data % - Fixed rotation for multiline text % 25-08-2012 - Special handling of 1xn char arrays for tick labels % (thanks to David Plavcan) % - Fix for 'Index exceeds matrix dimensions' of axis labels % (thanks to Aslak Grinsted) % - Fix for another axis label problem (thanks to Ben Mitch) % 15-09-2012 - Fix for linestyle none of rectangles (thanks to Andrew) % - Enabled scatter plot functionality % 16-02-2013 - Fix for manual tick labels if count differs from % number of ticks (thanks to Anna) % 18-07-2013 - Small fix to exclude change log from help % (thanks to Stuart Layton) % 30-11-2014 - Preliminary partial support for contour objects % Edits made by Jonathon Harding % 18-02-2015 - Removed calls to `find` inside variable indexes, as these % are not necessary for MATLAB % 18-02-2015 - Added MException catching to try/catch blocks and the % assocciated warning messages % 19-02-2015 - Updated line2svg to never create line segments longer than % 5000 points, even if the data includes some NaN elements % 19-02-2015 - convertunit now properly converts between MATLAB pixels % (which are variable) and SVG pixels (fixed at 90 ppi) in % all cases. Text will be appropriately sized when MATLAB is % run in High-DPI mode % 19-02-2015 - Updated text rendering code. Translation and rotation are % now applied in a single step, directly to the text object % (rather than in groups surrounding it). Super- and % sub-scripts are now generated using SVG standard values for % baseline-shift and font-size percentages % 19-02-2015 - Support for MATLAB 2014b grids added (Grids can have custom % opacity and colors). line2svg now supports opacity, % although MATLAB does not allow ordinary line objects to % have an alpha value, as far as I know % 19-02-2015 - Update for MATLAB 2015b: use axes OuterPosition for axes % placement % 19-02-2015 - Properly calculate the axes limits when the user has % specified infinite limits % 19-02-2015 - Added bug fix for when ticks are specified outside the plot % window % 19-02-2015 - Bug fix for log scale minor ticks not showing above the % largest power of 10. Inspired by Valentin, but used a % simpler solution % Edits made by Juerg Schwizer % 14-05-2015 - Reworked fix for ticks specified outside the plot window % - Added css property image-rendering: pixelated; % - Removed type 'image' from AxesChildBounds() as it triggers % an error under Matlab 2010. % 14-05-2015 - Reverted part of the text rendering of 19-02-2015 as it % failed to handle exponents. % 14-05-2015 - Removed undefined variable which was obsolete % Simon Blanchoud % 18-12-2014 - Modified to render uipanels properly % - Save now all images to a dedicated folder global PLOT2SVG_globals global colorname progversion='14-May-2015'; PLOT2SVG_globals.runningIdNumber = 0; PLOT2SVG_globals.octave = false; PLOT2SVG_globals.checkUserData = true; PLOT2SVG_globals.ScreenPixelsPerInch = 90; % Default 90ppi PLOT2SVG_globals.MainFigure = -1; PLOT2SVG_globals.used_dir = false; try PLOT2SVG_globals.ScreenPixelsPerInch = get(0, 'ScreenPixelsPerInch'); catch % Keep the default 90ppi end if nargout==1 varargout={0}; end disp([' Matlab/Octave to SVG converter version ' progversion ', Juerg Schwizer (converter@bluewin.ch).']) matversion=version; if exist('OCTAVE_VERSION','builtin') PLOT2SVG_globals.octave = true; disp(' Info: PLOT2SVG runs in Octave mode.') else if str2num(matversion(1))<6 % Check for matlab version and print warning if matlab version lower than version 6.0 (R.12) disp(' Warning: Future versions may no more support older versions than MATLAB R12.') end end if nargout > 1 error('Function returns only one return value.') end if nargin<2 % Check if handle was included into function call, otherwise take current figure id=gcf; end PLOT2SVG_globals.MainFigure = id; if nargin==0 || isnumeric(param1) [filename, pathname] = uiputfile( {'*.svg', 'SVG File (*.svg)'},'Save Figure as SVG File', pwd); if ~( isequal( filename, 0) || isequal( pathname, 0)) % yes. add backslash to path (if not already there) %pathname = addBackSlash( pathname); % check, if extension is allrigth if ( ~strcmpi( getFileExtension( filename), '.svg')) filename = [ filename, '.svg']; end finalname=fullfile(pathname, filename); %finalname=[pathname filename]; else disp(' Cancel button was pressed.') return end end if ~isnumeric(param1) finalname=param1; end % needed to see annotation axes originalShowHiddenHandles = get(0, 'ShowHiddenHandles'); set(0, 'ShowHiddenHandles', 'on'); originalFigureUnits=get(id,'Units'); set(id,'Units','pixels'); % All data in the svg-file is saved in pixels paperpos=get(id,'Position'); if ( nargin > 0) if isnumeric(param1) paperpos(3)=param1(1); paperpos(4)=param1(2); end end paperpos = convertunit(paperpos, 'pixels', 'pixels'); if (nargin < 3) PLOT2SVG_globals.pixelfiletype = 'png'; else PLOT2SVG_globals.pixelfiletype = pixelfiletype; end cmap=get(id,'Colormap'); colorname=''; for i=1:size(cmap,1) colorname(i,:)=sprintf('%02x%02x%02x',fix(cmap(i,1)*255),fix(cmap(i,2)*255),fix(cmap(i,3)*255)); end % Open SVG-file [pathstr,name] = fileparts(finalname); dirname = fullfile(pathstr, name); if (~isdir(dirname)) mkdir(dirname); end %PLOT2SVG_globals.basefilename = fullfile(pathstr,name); PLOT2SVG_globals.basefilepath = pathstr; PLOT2SVG_globals.basedirname = dirname; PLOT2SVG_globals.reldirname = fullfile('.', name); PLOT2SVG_globals.basefilename = name; PLOT2SVG_globals.figurenumber = 1; fid=fopen(finalname,'wt'); % Create a new text file fprintf(fid,'\n'); % Insert file header fprintf(fid,'\n'); fprintf(fid,' Matlab Figure Converted by PLOT2SVG written by Juerg Schwizer\n'); %fprintf(fid,' \n'); fprintf(fid,' \n'); group=1; groups=[]; % Frame of figure figcolor = searchcolor(id,get(id, 'Color')); if (~ strcmp(figcolor, 'none')) % Draw rectangle in the background of the graphic frame to cover all % other graphic elements try % Octave does not have support for InvertHardcopy yet -- Jakob Malm if strcmp(get(id,'InvertHardcopy'),'on') fprintf(fid,' \n',paperpos(3),paperpos(4)); else fprintf(fid,' \n',paperpos(3),paperpos(4),figcolor); end catch fprintf(fid,' \n',paperpos(3),paperpos(4),figcolor); end end % Search all axes group = children2svg(fid, id, id, group, paperpos); fprintf(fid,' \n'); fprintf(fid,'\n'); fclose(fid); % close text file if (~PLOT2SVG_globals.used_dir) rmdir(dirname); end if nargout==1 varargout={0}; end set(id,'Units',originalFigureUnits); set(0, 'ShowHiddenHandles', originalShowHiddenHandles); function group = children2svg(fid, id, child, group, paperpos) global PLOT2SVG_globals % Search all axes groups = []; ax=get(child,'Children'); for j=length(ax):-1:1 currenttype = get(ax(j),'Type'); if strcmp(currenttype,'axes') group=group+1; groups=[groups group]; group=axes2svg(fid,id,ax(j),group,paperpos); elseif strcmp(currenttype,'uicontrol') %if strcmp(get(ax(j),'Visible'),'on') % control2svg(fid,id,ax(j),group,paperpos); %end elseif strcmp(currenttype, 'uicontextmenu') || ... strcmp(currenttype, 'uimenu') || ... strcmp(currenttype, 'hgjavacomponent') || ... strcmp(currenttype, 'uitoolbar') % ignore these types elseif strcmp(currenttype, 'uipanel') %set(ax(j),'Units','pixels'); % All data in the svg-file is saved in pixels childpos=get(ax(j),'Position'); tmp_pos = childpos(1:2).*paperpos(3:4); %childpos = childpos * 90 / PLOT2SVG_globals.ScreenPixelsPerInch; childpos(2) = (1 - (childpos(2) + childpos(4))); childpos = childpos .* [paperpos(3:4) paperpos(3:4)]; group = group + 1; fprintf(fid,' \n', createId, childpos(1), childpos(2)); fprintf(fid,' \n',childpos(3),childpos(4)); children2svg(fid, id, ax(j), group, childpos); fprintf(fid,' \n'); else disp([' Warning: Unhandled main figure child type: ' currenttype]); end end function clippingIdString = clipping2svg(fid, id, ax, paperpos, axpos, projection, clippingIdString) global PLOT2SVG_globals if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData')) struct_data = get(id,'UserData'); if isfield(struct_data,'svg') if isfield(struct_data.svg,'ClippingPath') clip = struct_data.svg.ClippingPath; if ~isempty(clip) if size(clip, 2) ~=3 if size(clip, 2) ==2 clipx = clip(:, 1); clipy = clip(:, 2); clipz = zeros(size(clip,1),1); else error('The clipping vector has to be a nx3 or nx2 matrix.'); end else clipx = clip(:, 1); clipy = clip(:, 2); clipz = clip(:, 3); end if strcmp(get(ax,'XScale'),'log') clipx(clipx<=0) = NaN; clipx=log10(clipx); end if strcmp(get(ax,'YScale'),'log') clipy(clipy<=0) = NaN; clipy=log10(clipy); end if strcmp(get(ax,'ZScale'),'log') clipz(clipz<=0) = NaN; clipz=log10(clipz); end [x,y,z] = project(clipx,clipy,clipz,projection); x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); clippingIdString = createId; fprintf(fid,'\n \n\n'); end end end end function [angle, align] = improvedXLabel(id, angle, align) global PLOT2SVG_globals if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData')) struct_data = get(id,'UserData'); if isfield(struct_data,'svg') if isfield(struct_data.svg,'XTickLabelAngle') angle = struct_data.svg.XTickLabelAngle; align = 'Left'; end end end function [angle, align] = improvedYLabel(id, angle, align) global PLOT2SVG_globals if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData')) struct_data = get(id,'UserData'); if isfield(struct_data,'svg') if isfield(struct_data.svg,'YTickLabelAngle') angle = struct_data.svg.YTickLabelAngle; align = 'Left'; end end end function animation2svg(fid, id) global PLOT2SVG_globals if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData')) struct_data = get(id,'UserData'); if isfield(struct_data,'svg') if isfield(struct_data.svg,'Animation') animation = struct_data.svg.Animation; for i = 1:length(animation) if ~isfield(animation(i).SubAnimation, 'Type') error(['Missing field ''Type'' for animation.']); end switch animation(i).SubAnimation.Type case 'Opacity', type = 'opacity'; animationType = 0; case 'Translate', type = 'translate'; animationType = 2; case 'Scale', type = 'scale'; animationType = 2; case 'Rotate', type = 'rotate'; animationType = 1; case 'skewX', type = 'skewX'; animationType = 1; case 'skewY', type = 'skewY'; animationType = 1; otherwise, error(['Unknown animation type ''' animation(i).SubAnimation.Type '''.']); end %fprintf(fid,' ',... % 'opacity' , 0, 1, 5, 'indefinite'); if animationType == 0 fprintf(fid,' ', 'indefinite'); elseif animationType == 1 fprintf(fid,' ', 'indefinite'); elseif animationType == 2 fprintf(fid,' ', 'indefinite'); end end end end end function [filterString, boundingBox] = filter2svg(fid, id, boundingBoxAxes, boundingBoxElement) global PLOT2SVG_globals filterString = ''; boundingBox = boundingBoxAxes; if PLOT2SVG_globals.checkUserData && isstruct(get(id,'UserData')) struct_data = get(id,'UserData'); if isfield(struct_data,'svg') boundingBox = boundingBoxElement; absolute = true; offset = 0; if isfield(struct_data.svg,'BoundingBox') if isfield(struct_data.svg.BoundingBox, 'Type') switch struct_data.svg.BoundingBox.Type case 'axes', boundingBox = boundingBoxAxes; absolute = true; case 'element', boundingBox = boundingBoxElement; absolute = true; case 'relative', boundingBox = boundingBoxElement; absolute = false; otherwise error(['Unknown bounding box type ''' struct_data.svg.BoundingBox.Type '''.']); end end if isfield(struct_data.svg.BoundingBox, 'Overlap') overlap = struct_data.svg.BoundingBox.Overlap; if absolute boundingBox(1) = boundingBox(1) - overlap; boundingBox(2) = boundingBox(2) - overlap; boundingBox(3) = boundingBox(3) + 2 * overlap; boundingBox(4) = boundingBox(4) + 2 * overlap; else boundingBox(1) = boundingBox(1) - boundingBox(3) * overlap; boundingBox(2) = boundingBox(2) - boundingBox(4) * overlap; boundingBox(3) = boundingBox(3) + 2 * boundingBox(3) * overlap; boundingBox(4) = boundingBox(4) + 2 * boundingBox(4) * overlap; end end if isfield(struct_data.svg.BoundingBox, 'Visible') && strcmp(struct_data.svg.BoundingBox.Visible, 'on') % This functionality is very interesting for debugging of % bounding boxes of filters fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end end if isfield(struct_data.svg,'Filter') % Predefined filter sources. Additional filter sources will be % added later. predefinedSources = {'SourceGraphic','SourceAlpha','BackgroundImage','BackgroundAlpha','FillPaint','StrokePaint'}; resultStrings = predefinedSources; filterId = createId; filterString = ['filter="url(#' filterId ')"']; fprintf(fid,'\n'); fprintf(fid,' \n', 0, 0, 100, 100, filterId); %if absolute % fprintf(fid,' \n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4), filterId); %else % fprintf(fid,' \n', -(offset * 100), -(offset * 100), 100 + (offset * 200), 100 + (offset * 200), filterId); % % Note: use default -10% for attribute x % % use default -10% for attribute y % % use default 120% for attribute width % % use default 120% for attribute height %end filter = struct_data.svg.Filter; for i = 1:length(filter) if isfield(filter(i).Subfilter, 'Type') fprintf(fid,' <%s', filter(i).Subfilter.Type); else error(['Missing field ''Type'' for filter.']) end try if isfield(filter(i).Subfilter, 'Position') printAttributeArray(fid, {'x','y','width','height'}, filter(i).Subfilter, 'Position'); end printAttributeString(fid, 'result', filter(i).Subfilter, 'Result'); % Add result string to the list in order to check the in % strings. resultStrings{length(resultStrings) + 1} = filter(i).Subfilter.Result; % The strmatch below is a very inefficient search (Matlab limitation) if ~isempty(strmatch(filter(i).Subfilter.Result, predefinedSources)) error('Usage of a predefined filter source as filter result string is not allowed.'); end switch (filter(i).Subfilter.Type) case 'feGaussianBlur' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings); printAttributeDouble(fid, 'stdDeviation', filter(i).Subfilter, 'Deviation'); fprintf(fid,' />\n'); case 'feImage' printAttributeString(fid, 'xlink:href', filter(i).Subfilter, 'File'); printAttributeString(fid, 'preserveAspectRatio', filter(i).Subfilter, 'AspectRatio', 'xMidYMid meet'); fprintf(fid,' />\n'); case 'feComposite' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings); printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings); printAttributeList(fid, 'operator', filter(i).Subfilter, 'Operator', {'over','in','out','atop','xor','arithmetic'}, 'over'); % 'over' | 'in' | 'out' | 'atop' | 'xor' | 'arithmetic' if isfield(filter(i).Subfilter, 'Operator') && strcmp(filter(i).Subfilter.Operator, 'arithmetic') printAttributeArray(fid, {'k1','k2','k3','k4'}, filter(i).Subfilter, 'k'); end fprintf(fid,' />\n'); case 'feSpecularLighting' printAttributeDouble(fid, 'specularConstant', filter(i).Subfilter, 'SpecularConstant'); printAttributeDouble(fid, 'specularExponent', filter(i).Subfilter, 'SpecularExponent'); printAttributeDouble(fid, 'surfaceScale', filter(i).Subfilter, 'SurfaceScale'); fprintf(fid,' style="lighting-color:white"'); printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings); fprintf(fid,' >\n'); if isfield(filter(i).Subfilter, 'LightType') fprintf(fid,' <%s', filter(i).Subfilter.LightType); switch filter(i).Subfilter.LightType case 'feDistantLight' printAttributeDouble(fid, 'azimuth', filter(i).Subfilter, 'Azimuth'); printAttributeDouble(fid, 'elevation', filter(i).Subfilter, 'Elevation'); case 'fePointLight' printAttributeArray(fid, {'x','y','z'}, filter(i).Subfilter, 'Position'); case 'feSpotLight' printAttributeArray(fid, {'x','y','z'}, filter(i).Subfilter, 'Position'); printAttributeArray(fid, {'pointsAtX','pointsAtY','pointsAtZ'}, filter(i).Subfilter, 'PositionsAt'); printAttributeDouble(fid, 'specularExponent', filter(i).Subfilter, 'LightSpecularExponent'); printAttributeDouble(fid, 'limitingConeAngle', filter(i).Subfilter, 'LimitingConeAngle'); otherwise, error(['Unknown light type ''' filter(i).Subfilter.LightType ''.']); end fprintf(fid,' />\n'); else error('Missing field ''LightType''.'); end fprintf(fid,'\n',filter(i).Subfilter.Type); case 'feOffset' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings); printAttributeArray(fid, {'dx','dy'}, filter(i).Subfilter, 'Offset'); fprintf(fid,' />\n'); case 'feBlend' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings); printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings); printAttributeList(fid, 'mode', filter(i).Subfilter, 'Mode', {'normal','multiply','screen','darken','lighten'}, 'normal'); % 'normal' | 'multiply' | 'screen' | 'darken' | 'lighten' fprintf(fid,' />\n'); case 'feTurbulence' printAttributeDouble(fid, 'baseFrequency', filter(i).Subfilter, 'BaseFrequency'); printAttributeDouble(fid, 'numOctaves', filter(i).Subfilter, 'NumOctaves'); printAttributeDouble(fid, 'seed', filter(i).Subfilter, 'Seed'); printAttributeList(fid, 'stitchTiles', filter(i).Subfilter, 'StitchTiles', {'stitch','noStitch'}, 'noStitch'); % stitch | noStitch printAttributeList(fid, 'type', filter(i).Subfilter, 'TurbulenceType', {'fractalNoise','turbulence'}, 'turbulence'); % 'fractalNoise' | 'turbulence' fprintf(fid,' />\n'); case 'feColorMatrix' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings); printAttributeList(fid, 'type', filter(i).Subfilter, 'ColorType', {'matrix','saturate','hueRotate','luminanceToAlpha'}); % 'matrix' | 'saturate' | 'hueRotate' | 'luminanceToAlpha' if isfield(filter(i).Subfilter, 'ColorType') && strcmp(filter(i).Subfilter.ColorType, 'matrix') if isfield(filter(i).Subfilter, 'Matrix') && (lenght(filter(i).Subfilter.Matrix) == 20) fprintf(fid,' values="'); fprintf(fid,' %0.3f', filter(i).Subfilter.Matrix); fprintf(fid,'"'); else error('Field ''Matrix'' is missing or not a 5x4 matrix.'); end end if isfield(filter(i).Subfilter, 'ColorType') && (strcmp(filter(i).Subfilter.ColorType, 'saturate') || strcmp(filter(i).Subfilter.ColorType, 'hueRotate')) printAttributeDouble(fid, 'values', filter(i).Subfilter, 'Matrix'); end fprintf(fid,' />\n'); case 'feFlood' printAttributeColor(fid, 'flood-color', filter(i).Subfilter, 'Color'); printAttributeDouble(fid, 'flood-opacity', filter(i).Subfilter, 'Opacity'); fprintf(fid,' />\n'); case 'feDisplacementMap' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings); printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings); printAttributeDouble(fid, 'scale', filter(i).Subfilter, 'Scale'); printAttributeList(fid, 'xChannelSelector', filter(i).Subfilter, 'xChannel', {'R','G','B','A'}, 'A'); % 'R' | 'G' | 'B' | 'A' printAttributeList(fid, 'yChannelSelector', filter(i).Subfilter, 'yChannel', {'R','G','B','A'}, 'A'); % 'R' | 'G' | 'B' | 'A' fprintf(fid,' />\n'); case 'feMerge' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source1', 'SourceGraphic', resultStrings); printAttributeIn(fid, 'in2', filter(i).Subfilter, 'Source2', 'SourceGraphic', resultStrings); printAttributeList(fid, 'mode', filter(i).Subfilter, 'Mode', {'normal','multiply','screen','darken','lighten'}); % 'normal' | 'multiply' | 'screen' | 'darken' | 'lighten' fprintf(fid,' />\n'); case 'feMorphology' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings); printAttributeList(fid, 'operator', filter(i).Subfilter, 'Operator', {'erode','dilate'}); % 'erode' | 'dilate' printAttributeDouble(fid, 'radius', filter(i).Subfilter, 'Radius'); fprintf(fid,' />\n'); case 'feTile' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings); fprintf(fid,' />\n'); case 'feDiffuseLighting' printAttributeIn(fid, 'in', filter(i).Subfilter, 'Source', 'SourceGraphic', resultStrings); fprintf(fid,' style="lighting-color:white"'); printAttributeDouble(fid, 'surfaceScale', filter(i).Subfilter, 'SurfaceScale'); printAttributeDouble(fid, 'diffuseConstant', filter(i).Subfilter, 'DiffuseConstant'); printAttributeDouble(fid, 'kernelUnitLength', filter(i).Subfilter, 'KernelUnitLength'); fprintf(fid,' />\n'); % case 'feConvolveMatrix' % % printAttributeDouble(fid, 'order', filter(i).Subfilter); % kernelMatrix % printAttributeDouble(fid, 'divisor', filter(i).Subfilter, 1.0); % printAttributeDouble(fid, 'bias', filter(i).Subfilter, 0); % targetX % targetY % printAttributeString(fid, 'edgeMode', filter(i).Subfilter, 'EdgeMode', 'duplicate'); % fprintf(fid,' kernelUnitLength="1 1"'); % printAttributeString(fid, 'preserveAlpha', filter(i).Subfilter, 'PreserveAlpha', 'true'); % fprintf(fid,' />\n'); case {'feComponentTransfer','feConvolveMatrix'} error('Filter not yet implemented.'); otherwise error(['Unknown filter ''' filter(i).Subfilter.Type '''.']); end catch ME errStr = ME.identifier; if isempty(errStr) errStr = ME.message; end error([errStr ' Error is caused by filter type ''' filter(i).Subfilter.Type '''.']); end end fprintf(fid,' \n'); fprintf(fid,'\n'); end end end function printAttributeArray(fid, names, svgstruct, svgfield) if isfield(svgstruct, svgfield) if isnumeric(svgstruct.(svgfield)) if length(svgstruct.(svgfield)) ~= length(names) error(['Length mismatch for field ''' svgfield '''.']) end for i = 1:length(names) fprintf(fid,' %s="%0.3f"', names{i}, svgstruct.(svgfield)(i)); end else error(['Field ''' svgfield ''' must be numeric.']); end else if nargin < 5 error(['Missing field ''' svgfield '''.']) else for i = 1:length(names) fprintf(fid,' %s="%0.3f"', names{i}, default(i)); end end end function printAttributeDouble(fid, name, svgstruct, svgfield, default) if isfield(svgstruct, svgfield) if isnumeric(svgstruct.(svgfield)) fprintf(fid,' %s="%0.3f"', name, svgstruct.(svgfield)); else error(['Field ''' svgfield ''' must be numeric.']); end else if nargin < 5 error(['Missing field ''' svgfield '''.']) else fprintf(fid,' %s="%0.3f"', name, default); end end function printAttributeIn(fid, name, svgstruct, svgfield, default, resultStrings) if isfield(svgstruct, svgfield) if ischar(svgstruct.(svgfield)) % The strmatch below is a very inefficient search (Matlab limitation) if isempty(strmatch(svgstruct.(svgfield), resultStrings)) error(['The source string ''' svgstruct.(svgfield) ''' was never a result string of a previous filter. Check for correct spelling.']); else fprintf(fid,' %s="%s"', name, svgstruct.(svgfield)); end else error(['Field ''' svgfield ''' must be a string.']); end else if nargin < 5 error(['Missing field ''' svgfield '''.']) else fprintf(fid,' %s="%s"', name, default); end end function printAttributeString(fid, name, svgstruct, svgfield, default) if isfield(svgstruct, svgfield) if ischar(svgstruct.(svgfield)) fprintf(fid,' %s="%s"', name, svgstruct.(svgfield)); else error(['Field ''' svgfield ''' must be a string.']); end else if nargin < 5 error(['Missing field ''' svgfield '''.']) else fprintf(fid,' %s="%s"', name, default); end end function printAttributeList(fid, name, svgstruct, svgfield, list, default) if isfield(svgstruct, svgfield) if ischar(svgstruct.(svgfield)) if isempty(strmatch(svgstruct.(svgfield), list)) listString = strcat(list, ''' | '''); listString = [listString{:}]; error(['Illegal string identifier ''' svgstruct.(svgfield) '''. Must be one out of the list: ''' listString(1:end-4) '.']); else fprintf(fid,' %s="%s"', name, svgstruct.(svgfield)); end else error(['Field ''' svgfield ''' must be a string.']); end else if nargin < 6 error(['Missing field ''' svgfield '''.']) else fprintf(fid,' %s="%s"', name, default); end end function printAttributeColor(fid, name, svgstruct, svgfield, default) if isfield(svgstruct, svgfield) if isnumeric(svgstruct.(svgfield)) if length(svgstruct.(svgfield)) ~= 3 error(['Color must be a 1x3 vector for field ''' svgfield '''.']) else fprintf(fid,' %s="%s"', name, searchcolor(gca, svgstruct.(svgfield))); end else error(['Field ''' svgfield ''' must be a 1x3 vector.']); end else if nargin < 5 error(['Missing field ''' svgfield '''.']) else fprintf(fid,' %s="%s"', name, default); end end function frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, tick, index, edge_neighbours, c, valid_ticks, ticklength, tick_ratio, lim, drawBorder) for k = 1:length(index) x_tick_end1 = interp1([0 1],[x(index(k)) x(edge_neighbours(index(k),c(1)))],ticklength*tick_ratio(c(3)),'linear','extrap'); y_tick_end1 = interp1([0 1],[y(index(k)) y(edge_neighbours(index(k),c(1)))],ticklength*tick_ratio(c(3)),'linear','extrap'); 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'); 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'); xg_line_start = interp1(lim,[x(index(k)) x(edge_neighbours(index(k),c(2)))],tick); yg_line_start = interp1(lim,[y(index(k)) y(edge_neighbours(index(k),c(2)))],tick); xg_line_end = interp1(lim,[x_tick_end1 x_tick_end2],tick); yg_line_end = interp1(lim,[y_tick_end1 y_tick_end2],tick); for i = valid_ticks line2svg(fid,grouplabel,axpos,[xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)],scolorname,'-',linewidth) end if drawBorder 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) end end function gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlim, axtick, axindex_inner, corners, c, gridAlpha) xg_line_start = interp1([axlim(1) axlim(2)],[x(corners(c(1))) x(corners(c(2)))], axtick); yg_line_start = interp1([axlim(1) axlim(2)],[y(corners(c(1))) y(corners(c(2)))], axtick); xg_line_end = interp1([axlim(1) axlim(2)],[x(corners(c(3))) x(corners(c(4)))], axtick); yg_line_end = interp1([axlim(1) axlim(2)],[y(corners(c(3))) y(corners(c(4)))], axtick); if nargin < 14 || isempty(gridAlpha) gridAlpha = 1; end for i = axindex_inner line2svg(fid, grouplabel, axpos, [xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)], scolorname, gridlinestyle, linewidth, gridAlpha) end function minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlim, minor_axtick, corners, c, gridAlpha) xg_line_start = interp1([axlim(1) axlim(2)],[x(corners(c(1))) x(corners(c(2)))], minor_axtick); yg_line_start = interp1([axlim(1) axlim(2)],[y(corners(c(1))) y(corners(c(2)))], minor_axtick); xg_line_end = interp1([axlim(1) axlim(2)],[x(corners(c(3))) x(corners(c(4)))], minor_axtick); yg_line_end = interp1([axlim(1) axlim(2)],[y(corners(c(3))) y(corners(c(4)))], minor_axtick); if nargin < 14 || isempty(gridAlpha) gridAlpha = 1; end for i = 1:length(xg_line_start) line2svg(fid, grouplabel, axpos, [xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)], scolorname, minor_gridlinestyle, linewidth, gridAlpha) end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SUBFUNCTIONS %%%%% % Create axis frame and insert all children of this axis frame function group=axes2svg(fid,id,ax,group,paperpos) global colorname global PLOT2SVG_globals originalAxesUnits=get(ax,'Units'); set(ax,'Units','normalized'); axpos=get(ax,'Position'); 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]; % x-y ; y-z ; x-z ; y-z ; x-z ; x-y corners(:,:,1) = [1 1 2 3 4; 2 1 3 2 4]; corners(:,:,2) = [2 2 4 6 8; 3 2 6 4 8]; corners(:,:,3) = [1 3 4 7 8; 3 3 7 4 8]; corners(:,:,4) = [1 1 2 5 6; 3 1 5 2 6]; corners(:,:,5) = [2 1 3 5 7; 3 1 5 3 7]; corners(:,:,6) = [1 5 6 7 8; 2 5 7 6 8]; 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]; edge_opposite = [8 7 6 5 4 3 2 1]; nomx = [0 1 0 1 0 1 0 1]; nomy = [0 0 1 1 0 0 1 1]; nomz = [0 0 0 0 1 1 1 1]; [projection,edges] = get_projection(ax,id); x = (edges(1,:)*axpos(3)+axpos(1))*paperpos(3); y = (1-(edges(2,:)*axpos(4)+axpos(2)))*paperpos(4); % Depth Sort of view box edges [edge_z,edge_index]=sort(edges(3,:)); most_back_edge_index = edge_index(1); % Back faces are plot box faces that are behind the plot (as seen by the % view point) back_faces = find(any(faces == most_back_edge_index,2)); front_faces = find(all(faces ~= most_back_edge_index,2)); groupax=group; axlimx=get(ax,'XLim'); axlimy=get(ax,'YLim'); axlimz=get(ax,'ZLim'); [axinflimx, axinflimy, axinflimz] = AxesChildBounds(ax); axlimx(isinf(axlimx)) = axinflimx(isinf(axlimx)); axlimy(isinf(axlimy)) = axinflimy(isinf(axlimy)); axlimz(isinf(axlimz)) = axinflimz(isinf(axlimz)); axlimxori=axlimx; axlimyori=axlimy; axlimzori=axlimz; if strcmp(get(ax,'XScale'),'log') axlimx=log10(axlimx); axlimx(isinf(axlimx))=0; end if strcmp(get(ax,'YScale'),'log') axlimy=log10(axlimy); axlimy(isinf(axlimy))=0; end if strcmp(get(ax,'ZScale'),'log') axlimz=log10(axlimz); axlimz(isinf(axlimz))=0; end if strcmp(get(ax,'XDir'),'reverse') axlimx = fliplr(axlimx); end if strcmp(get(ax,'YDir'),'reverse') axlimy = fliplr(axlimy); end if strcmp(get(ax,'ZDir'),'reverse') axlimz = fliplr(axlimz); end axlimori = [axlimxori(1) axlimyori(1) axlimzori(1) axlimxori(2)-axlimxori(1) axlimyori(2)-axlimyori(1) axlimzori(2)-axlimzori(1)]; fprintf(fid,' \n', createId); axIdString = createId; boundingBoxAxes = [min(x) min(y) max(x)-min(x) max(y)-min(y)]; fprintf(fid,' \n',axIdString); fprintf(fid,' \n',... boundingBoxAxes(1), boundingBoxAxes(2), boundingBoxAxes(3), boundingBoxAxes(4)); fprintf(fid,' \n'); if strcmp(get(ax,'Visible'),'on') group=group+1; grouplabel=group; axxtick=get(ax,'XTick'); axytick=get(ax,'YTick'); axztick=get(ax,'ZTick'); axlabelx=get(ax,'XTickLabel'); axlabely=get(ax,'YTickLabel'); axlabelz=get(ax,'ZTickLabel'); % Workaround for Octave if PLOT2SVG_globals.octave if isempty(axlabelx) if strcmp(get(ax,'XScale'),'log') axlabelx = num2str(log10(axxtick)'); else axlabelx = num2str(axxtick'); end end if isempty(axlabely) if strcmp(get(ax,'YScale'),'log') axlabely = num2str(log10(axytick)'); else axlabely = num2str(axytick'); end end if isempty(axlabelz) if strcmp(get(ax,'ZScale'),'log') axlabelz = num2str(log10(axztick)'); else axlabelz = num2str(axztick'); end end if projection.xyplane axlabelz = []; end end gridlinestyle=get(ax,'GridLineStyle'); minor_gridlinestyle=get(ax,'MinorGridLineStyle'); try % Octave does not have 'TickLength' yet. --Jakob Malm both_ticklength = get(ax,'TickLength'); catch both_ticklength = [ 0.01 0.025 ]; end gridBehind = true; % Default setting try if strcmp(get(ax, 'Layer'), 'top') && projection.xyplane gridBehind = false; end catch gridBehind = true; end if projection.xyplane ticklength = both_ticklength(1); xy_ratio = axpos(3)*paperpos(3)/ (axpos(4)*paperpos(4)); if xy_ratio < 1 tick_ratio = [1 1/xy_ratio 1]; else tick_ratio = [xy_ratio 1 1]; end if strcmp(get(ax,'TickDir'),'out') label_distance = -(0.02 + ticklength); else label_distance = -0.02; end else ticklength = both_ticklength(2); label_distance = -2*abs(ticklength); tick_ratio = [1 1 1]; end linewidth = get(ax,'LineWidth'); axxindex=find((axxtick >= axlimori(1)) & (axxtick <= (axlimori(1)+axlimori(4)))); axyindex=find((axytick >= axlimori(2)) & (axytick <= (axlimori(2)+axlimori(5)))); axzindex=find((axztick >= axlimori(3)) & (axztick <= (axlimori(3)+axlimori(6)))); % remove sticks outside of the axes (-1 of legends) axxtick=axxtick(axxindex); axytick=axytick(axyindex); axztick=axztick(axzindex); if length(axxtick) > 1 minor_lin_sticks = (0.2:0.2:0.8)*(axxtick(2)-axxtick(1)); minor_axxtick = []; for stick = [2*axxtick(1)-axxtick(2) axxtick] minor_axxtick = [minor_axxtick minor_lin_sticks + stick]; end minor_axxtick = minor_axxtick(minor_axxtick > min(axlimx) & minor_axxtick < max(axlimx)); else minor_axxtick = []; end if length(axytick) > 1 minor_lin_sticks = (0.2:0.2:0.8)*(axytick(2)-axytick(1)); minor_axytick = []; for stick = [2*axytick(1)-axytick(2) axytick] minor_axytick = [minor_axytick minor_lin_sticks + stick]; end minor_axytick = minor_axytick(minor_axytick > min(axlimy) & minor_axytick < max(axlimy)); else minor_axytick = []; end if length(axztick) > 1 minor_lin_sticks = (0.2:0.2:0.8)*(axztick(2)-axztick(1)); minor_axztick = []; for stick = [2*axztick(1)-axztick(2) axztick] minor_axztick = [minor_axztick minor_lin_sticks + stick]; end minor_axztick = minor_axztick(minor_axztick > min(axlimz) & minor_axztick < max(axlimz)); else minor_axztick = []; end if strcmp(get(ax,'Box'),'on') axxindex_inner = find((axxtick > axlimori(1)) & (axxtick < (axlimori(1)+axlimori(4)))); axyindex_inner = find((axytick > axlimori(2)) & (axytick < (axlimori(2)+axlimori(5)))); axzindex_inner = find((axztick > axlimori(3)) & (axztick < (axlimori(3)+axlimori(6)))); else axxindex_inner = find((axxtick >= axlimori(1)) & (axxtick <= (axlimori(1)+axlimori(4)))); axyindex_inner = find((axytick >= axlimori(2)) & (axytick <= (axlimori(2)+axlimori(5)))); axzindex_inner = find((axztick >= axlimori(3)) & (axztick <= (axlimori(3)+axlimori(6)))); end minor_log_sticks = log10(0.2:0.1:0.9); if strcmp(get(ax,'TickDir'),'out') ticklength=-ticklength; valid_xsticks = 1:length(axxindex); valid_ysticks = 1:length(axyindex); valid_zsticks = 1:length(axzindex); else valid_xsticks = axxindex_inner; valid_ysticks = axyindex_inner; valid_zsticks = axzindex_inner; end if strcmp(get(ax,'XScale'),'log') axxtick = log10(get(ax,'XTick')); minor_axxtick = []; if ~isempty(axxtick) all_axxtick = axxtick(1):1:(axxtick(end) + 1); for stick = all_axxtick minor_axxtick = [minor_axxtick minor_log_sticks + stick]; end end minor_axxtick = minor_axxtick(minor_axxtick > min(axlimx) & minor_axxtick < max(axlimx)); end if strcmp(get(ax,'YScale'),'log') axytick=log10(get(ax,'YTick')); minor_axytick = []; if ~isempty(axytick) all_axytick = axytick(1):1:(axytick(end) + 1); for stick = all_axytick minor_axytick = [minor_axytick minor_log_sticks + stick]; end end minor_axytick = minor_axytick(minor_axytick > min(axlimy) & minor_axytick < max(axlimy)); end if strcmp(get(ax,'ZScale'),'log') axztick=log10(get(ax,'ZTick')); minor_axztick = []; if ~isempty(axztick) all_axztick = axztick(1):1:(axztick(end) + 1); for stick = all_axztick minor_axztick = [minor_axztick minor_log_sticks + stick]; end end minor_axztick = minor_axztick(minor_axztick > min(axlimz) & minor_axztick < max(axlimz)); end % Draw back faces linewidth=get(ax,'LineWidth'); if ~strcmp(get(ax,'Color'),'none') background_color = searchcolor(id,get(ax,'Color')); background_opacity = 1; else background_color = '#000000'; background_opacity = 0; end for p=1:size(back_faces) patch2svg(fid, group, axpos, x(faces(back_faces(p),:)), y(faces(back_faces(p),:)), background_color, '-', linewidth, 'none', background_opacity, 1.0, true) end for pindex = 1:size(back_faces) p = back_faces(pindex); for k = 1:size(corners,1) selectedCorners = squeeze(corners(k,:,p)); gridAlpha = get(ax, 'GridAlpha'); minorGridAlpha = get(ax, 'MinorGridAlpha'); switch corners(k,1,p) case 1 % x % Draw x-grid if strcmp(get(ax, 'GridColorMode'), 'auto') scolorname = get(ax, 'XColor'); else scolorname = get(ax, 'GridColor'); end scolorname = searchcolor(id,scolorname); if strcmp(get(ax,'XGrid'),'on') && gridBehind if axlimx(1)~=axlimx(2) gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimx, axxtick, axxindex_inner, selectedCorners, [2 3 4 5], gridAlpha) if strcmp(get(ax,'XTickMode'),'auto') && strcmp(get(ax,'XMinorGrid'),'on') && ~isempty(minor_axxtick) minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimx, minor_axxtick, selectedCorners, [2 3 4 5], minorGridAlpha) end end end if projection.xyplane == false if strcmp(get(ax,'Box'),'on') 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); 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); else if strcmp(get(ax,'XGrid'),'on') 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); 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); end end end case 2 % y % Draw y-grid if strcmp(get(ax, 'GridColorMode'), 'auto') scolorname = get(ax, 'YColor'); else scolorname = get(ax, 'GridColor'); end scolorname = searchcolor(id,scolorname); if strcmp(get(ax,'YGrid'),'on') && gridBehind if axlimy(1)~=axlimy(2) gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimy, axytick, axyindex_inner, selectedCorners, [2 3 4 5], gridAlpha) if strcmp(get(ax,'YTickMode'),'auto') && strcmp(get(ax,'YMinorGrid'),'on') && ~isempty(minor_axytick) minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimy, minor_axytick, selectedCorners, [2 3 4 5], minorGridAlpha) end end end if projection.xyplane == false if strcmp(get(ax,'Box'),'on') 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); 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); else if strcmp(get(ax,'YGrid'),'on') 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); 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); end end end case 3 % z % Draw z-grid if strcmp(get(ax, 'GridColorMode'), 'auto') scolorname = get(ax, 'ZColor'); else scolorname = get(ax, 'GridColor'); end scolorname = searchcolor(id,scolorname); if strcmp(get(ax,'ZGrid'),'on') && gridBehind if axlimz(1)~=axlimz(2) gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimz, axztick, axzindex_inner, selectedCorners, [2 3 4 5], gridAlpha) if strcmp(get(ax,'ZTickMode'),'auto') && strcmp(get(ax,'ZMinorGrid'),'on') && ~isempty(minor_axztick) minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimz, minor_axztick, selectedCorners, [2 3 4 5], minorGridAlpha) end end end if projection.xyplane == false if strcmp(get(ax,'Box'),'on') 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); 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); else if strcmp(get(ax,'ZGrid'),'on') 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); 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); end end end end end end end fprintf(fid,' \n'); axchild=get(ax,'Children'); if ~PLOT2SVG_globals.octave %if ~verLessThan('matlab','8.4.0') % Matlab h2 engine axchild = [axchild; ax.Title; ax.XLabel; ax.YLabel; ax.ZLabel]; end group = axchild2svg(fid,id,axIdString,ax,group,paperpos,axchild,axpos,groupax,projection,boundingBoxAxes); fprintf(fid,' \n'); if strcmp(get(ax,'Visible'),'on') fprintf(fid,' \n'); % Search axis for labeling if projection.xyplane [x_axis_point_value, x_axis_point_index_top] = min(y); [x_axis_point_value, x_axis_point_index_bottom] = max(y); if strcmp(get(ax,'Box'),'on') if strcmp(get(ax,'XAxisLocation'),'top') x_axis_point_index = [x_axis_point_index_top x_axis_point_index_bottom]; else x_axis_point_index = [x_axis_point_index_bottom x_axis_point_index_top]; end else if strcmp(get(ax,'XAxisLocation'),'top') x_axis_point_index = x_axis_point_index_top; else x_axis_point_index = x_axis_point_index_bottom; end end [y_axis_point_value, y_axis_point_index_left] = min(x); [y_axis_point_value, y_axis_point_index_right] = max(x); if strcmp(get(ax,'Box'),'on') if strcmp(get(ax,'YAxisLocation'),'right') y_axis_point_index = [y_axis_point_index_right y_axis_point_index_left]; else y_axis_point_index = [y_axis_point_index_left y_axis_point_index_right]; end else if strcmp(get(ax,'YAxisLocation'),'right') y_axis_point_index = y_axis_point_index_right; else y_axis_point_index = y_axis_point_index_left; end end [z_axis_point_value, z_axis_point_index] = min(x); else [x_axis_point_value, x_axis_point_index] = max(y); [y_axis_value, y_axis_point_index] = max(y); [z_axis_point_value, z_axis_point_index] = min(x); end % Draw grid for pindex = 1:size(front_faces) p = front_faces(pindex); for k = 1:size(corners,1) selectedCorners = squeeze(corners(k,:,p)); switch corners(k,1,p) case 1 % x % Draw x-grid scolorname = searchcolor(id,get(ax,'XColor')); if strcmp(get(ax,'XGrid'),'on') && gridBehind == false if axlimx(1)~=axlimx(2) gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimx, axxtick, axxindex_inner, selectedCorners, [2 3 4 5]) if strcmp(get(ax,'XTickMode'),'auto') && strcmp(get(ax,'XMinorGrid'),'on') && ~isempty(minor_axxtick) minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimx, minor_axxtick, selectedCorners, [2 3 4 5]) end end end case 2 % y % Draw y-grid scolorname = searchcolor(id,get(ax,'YColor')); if strcmp(get(ax,'YGrid'),'on') && gridBehind == false if axlimy(1)~=axlimy(2) gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimy, axytick, axyindex_inner, selectedCorners, [2 3 4 5]) if strcmp(get(ax,'YTickMode'),'auto') && strcmp(get(ax,'YMinorGrid'),'on') && ~isempty(minor_axytick) minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimy, minor_axytick, selectedCorners, [2 3 4 5]) end end end case 3 % z % Draw z-grid scolorname = searchcolor(id,get(ax,'ZColor')); if strcmp(get(ax,'ZGrid'),'on') && gridBehind == false if axlimz(1)~=axlimz(2) gridLines(fid, grouplabel, axpos, x, y, scolorname, gridlinestyle, linewidth, axlimz, axztick, axzindex_inner, selectedCorners, [2 3 4 5]) if strcmp(get(ax,'ZTickMode'),'auto') && strcmp(get(ax,'ZMinorGrid'),'on') && ~isempty(minor_axztick) minorGridLines(fid, grouplabel, axpos, x, y, scolorname, minor_gridlinestyle, linewidth, axlimz, minor_axztick, selectedCorners, [2 3 4 5]) end end end end end end scolorname=searchcolor(id,get(ax,'XColor')); % Draw 'box' of x-axis if projection.xyplane == false if strcmp(get(ax,'Box'),'on') edge_line_index = [edge_opposite(most_back_edge_index) edge_neighbours(edge_opposite(most_back_edge_index),1)]; line2svg(fid,grouplabel,axpos,x(edge_line_index),y(edge_line_index),scolorname,'-',linewidth) end end % Draw x-tick labels if (strcmp(get(ax,'XTickLabelMode'),'auto') && strcmp(get(ax,'XScale'),'log')) exponent = 1; else exponent = 0; end % Draw x-tick marks if (ticklength(1) ~= 0) if axlimx(1)~=axlimx(2) if (nomx(x_axis_point_index(1))) lim = [axlimx(2) axlimx(1)]; else lim = [axlimx(1) axlimx(2)]; end 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'); 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'); 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'); 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'); xg_label_end = interp1(lim,[x_label_end1 x_label_end2],axxtick); yg_label_end = interp1(lim,[y_label_end1 y_label_end2],axxtick); frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ... axxtick, x_axis_point_index, edge_neighbours, [2 1 1], ... valid_xsticks, ticklength, tick_ratio, lim, true); if strcmp(get(ax,'XTickMode'),'auto') && (strcmp(get(ax,'XMinorGrid'),'on') || strcmp(get(ax,'XScale'),'log')) && ~isempty(minor_axxtick) frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ... minor_axxtick, x_axis_point_index, edge_neighbours, [2 1 1], ... 1:length(minor_axxtick), 0.5 * ticklength, tick_ratio, lim, false); end if ~isempty(axlabelx) && ~(iscell(axlabelx) && all(cellfun(@isempty,axlabelx))) if ischar(axlabelx) && size(axlabelx, 1) == 1 % Special handling of 1xn char arrays -> duplicate data % for all ticks. Strange behavior but follows the % behavior of Matlab axlabelx = repmat(axlabelx, length(axxindex), 1); end % Note: 3D plot do not support the property XAxisLocation % setting 'top'. [angle, align] = improvedXLabel(ax, 0, 'Center'); if (strcmp(get(ax,'XTickLabelMode'),'manual')) axlabelx = axlabelx(axxindex,:); end if strcmp(get(ax,'XAxisLocation'),'top') && (projection.xyplane == true) for i = 1:length(axxindex) if iscell(axlabelx) label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelx{i}),align,angle,'bottom',1,paperpos,scolorname,exponent); else label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelx(i,:)),align,angle,'bottom',1,paperpos,scolorname,exponent); end end else for i = 1:length(axxindex) if iscell(axlabelx) label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelx{i}),align,angle,'top',1,paperpos,scolorname,exponent); else label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelx(i,:)),align,angle,'top',1,paperpos,scolorname,exponent); end end end end end end scolorname=searchcolor(id,get(ax,'YColor')); % Draw 'box' of y-axis if projection.xyplane == false if strcmp(get(ax,'Box'),'on') edge_line_index = [edge_opposite(most_back_edge_index) edge_neighbours(edge_opposite(most_back_edge_index),2)]; line2svg(fid,grouplabel,axpos,x(edge_line_index),y(edge_line_index),scolorname,'-',linewidth) end end % Draw y-tick labels if (strcmp(get(ax,'YTickLabelMode'),'auto') && strcmp(get(ax,'YScale'),'log')) exponent = 1; else exponent = 0; end % Draw y-tick marks if (ticklength(1) ~= 0) if axlimy(1)~=axlimy(2) if (nomy(y_axis_point_index(1))) lim = [axlimy(2) axlimy(1)]; else lim = [axlimy(1) axlimy(2)]; end 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'); 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'); 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'); 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'); xg_label_end = interp1(lim,[x_label_end1 x_label_end2],axytick); yg_label_end = interp1(lim,[y_label_end1 y_label_end2],axytick); frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ... axytick, y_axis_point_index, edge_neighbours, [1 2 2], ... valid_ysticks, ticklength, tick_ratio, lim, true); if strcmp(get(ax,'YTickMode'),'auto') && (strcmp(get(ax,'YMinorGrid'),'on') || strcmp(get(ax,'YScale'),'log')) && ~isempty(minor_axytick) frontTicks(fid, grouplabel, axpos, x, y, scolorname, linewidth, ... minor_axytick, y_axis_point_index, edge_neighbours, [1 2 2], ... 1:length(minor_axytick), 0.5 * ticklength, tick_ratio, lim, false); end if ~isempty(axlabely) && ~(iscell(axlabely) && all(cellfun(@isempty,axlabely))) if ischar(axlabely) && size(axlabely, 1) == 1 % Special handling of 1xn char arrays -> duplicate data % for all ticks. Strange behavior but follows the % behavior of Matlab axlabely = repmat(axlabely, length(axyindex), 1); end % Note: 3D plot do not support the property YAxisLocation % setting 'right'. if (strcmp(get(ax,'YTickLabelMode'),'manual')) axlabely = axlabely(axyindex,:); end if (projection.xyplane == true) if strcmp(get(ax,'YAxisLocation'),'right') [angle, align] = improvedYLabel(ax, 0, 'Left'); for i = 1:length(axyindex) if iscell(axlabely) label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely{i}),align,angle,'middle',1,paperpos,scolorname,exponent); else label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely(i,:)),align,angle,'middle',1,paperpos,scolorname,exponent); end end else [angle, align] = improvedYLabel(ax, 0, 'Right'); for i = 1:length(axyindex) if iscell(axlabely) label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely{i}),align,angle,'middle',1,paperpos,scolorname,exponent); else label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely(i,:)),align,angle,'middle',1,paperpos,scolorname,exponent); end end end else for i = 1:length(axyindex) label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabely(i,:)),'Center',0,'top',1,paperpos,scolorname,exponent); end end end end end scolorname=searchcolor(id,get(ax,'ZColor')); % Draw 'box' of z-axis if projection.xyplane == false if strcmp(get(ax,'Box'),'on') edge_line_index = [edge_opposite(most_back_edge_index) edge_neighbours(edge_opposite(most_back_edge_index),3)]; line2svg(fid,grouplabel,axpos,x(edge_line_index),y(edge_line_index),scolorname,'-',linewidth) end end if (strcmp(get(ax,'ZTickLabelMode'),'auto') && strcmp(get(ax,'ZScale'),'log')) exponent = 1; else exponent = 0; end % Draw z-tick marks if (ticklength(1) ~= 0) if axlimz(1)~=axlimz(2) if (nomz(z_axis_point_index(1))) lim = [axlimz(2) axlimz(1)]; else lim = [axlimz(1) axlimz(2)]; end 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'); 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'); 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'); 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'); x_label_end1 = interp1([0 1],[x(z_axis_point_index) x(edge_neighbours(z_axis_point_index,2))],label_distance,'linear','extrap'); y_label_end1 = interp1([0 1],[y(z_axis_point_index) y(edge_neighbours(z_axis_point_index,2))],label_distance,'linear','extrap'); 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'); 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'); xg_line_start = interp1(lim,[x(z_axis_point_index) x(edge_neighbours(z_axis_point_index,3))],axztick); yg_line_start = interp1(lim,[y(z_axis_point_index) y(edge_neighbours(z_axis_point_index,3))],axztick); xg_line_end = interp1(lim,[x_tick_end1 x_tick_end2],axztick); yg_line_end = interp1(lim,[y_tick_end1 y_tick_end2],axztick); xg_label_end = interp1(lim,[x_label_end1 x_label_end2],axztick); yg_label_end = interp1(lim,[y_label_end1 y_label_end2],axztick); for i = valid_zsticks line2svg(fid,grouplabel,axpos,[xg_line_start(i) xg_line_end(i)],[yg_line_start(i) yg_line_end(i)],scolorname,'-',linewidth) end 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) if ~isempty(axlabelz) && ~(iscell(axlabelz) && all(cellfun(@isempty,axlabelz))) if ischar(axlabelz) && size(axlabelz, 1) == 1 % Special handling of 1xn char arrays -> duplicate data % for all ticks. Strange behavior but follows the % behavior of Matlab axlabelz = repmat(axlabelz, length(axzindex), 1); end if (strcmp(get(ax,'ZTickLabelMode'),'manual')) axlabelz = axlabelz(axzindex,:); end for i = 1:length(axzindex) label2svg(fid,grouplabel,axpos,ax,xg_label_end(i),yg_label_end(i),convertString(axlabelz(i,:)),'Right',0,'middle',1,paperpos,scolorname,exponent); end end end end exponent2svg(fid,groupax,axpos,paperpos,ax,axxtick,axytick,axztick) fprintf(fid,' \n'); end fprintf(fid,' \n'); set(ax,'Units',originalAxesUnits); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % take any axis children and create objects for them function group=axchild2svg(fid,id,axIdString,ax,group,paperpos,axchild,axpos,groupax,projection,boundingBoxAxes) global colorname global PLOT2SVG_globals for i=length(axchild):-1:1 if strcmp(get(axchild(i), 'Visible'), 'off') % do nothing elseif strcmp(get(axchild(i),'Type'),'scatter') linewidth=get(axchild(i),'LineWidth'); marker=get(axchild(i),'Marker'); markeredgecolor=get(axchild(i),'MarkerEdgeColor'); if ischar(markeredgecolor) if strcmp(markeredgecolor, 'flat') markeredgecolorname=searchcolor(id,get(axchild(i), 'CData')); else markeredgecolorname=markeredgecolor; end else markeredgecolorname=searchcolor(id,markeredgecolor); end markerfacecolor=get(axchild(i),'MarkerFaceColor'); if ischar(markerfacecolor) markerfacecolorname=markerfacecolor; else markerfacecolorname=searchcolor(id,markerfacecolor); end markersize=get(axchild(i),'SizeData'); switch marker case 'none'; case {'.','o','*'},markersize=sqrt(markersize/pi); otherwise,markersize=sqrt(markersize); end linex = get(axchild(i),'XData'); linex = linex(:)'; % Octave stores the data in a column vector if strcmp(get(ax,'XScale'),'log') linex(linex<=0) = NaN; linex=log10(linex); end liney=get(axchild(i),'YData'); liney = liney(:)'; % Octave stores the data in a column vector if strcmp(get(ax,'YScale'),'log') liney(liney<=0) = NaN; liney=log10(liney); end linez=get(axchild(i),'ZData'); linez = linez(:)'; % Octave stores the data in a column vector if isempty(linez) linez = zeros(size(linex)); end if strcmp(get(ax,'ZScale'),'log') linez(linez<=0) = NaN; linez=log10(linez); end [x,y,z] = project(linex,liney,linez,projection); x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); markerOverlap = 0; if ~strcmp(marker, 'none') markerOverlap = max(markerOverlap, convertunit(markersize, 'points', 'pixels', axpos(4))); end boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap]; [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement); % put a line into a group with its markers if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); else fprintf(fid,'\n', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end % put the markers into a subgroup of the lines if ~strcmp(marker, 'none') % but only do it if we actually are drawing markers fprintf(fid,'\n'); switch marker case 'none'; case '.',group=group+1;circle2svg(fid,group,axpos,x,y,markersize*0.25,'none',markeredgecolorname,linewidth); case 'o',group=group+1;circle2svg(fid,group,axpos,x,y,markersize,markeredgecolorname,markerfacecolorname,linewidth); 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); 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); 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); %% Octave keeps s, d, p and h in the HandleGraphics object, for the square, diamond, pentagram, and hexagram markers, respectively -- Jakob Malm 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); 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); case {'pentagram', 'p'},group=group+1;patch2svg(fid,group,axpos,... 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,... 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); case {'hexagram', 'h'},group=group+1;patch2svg(fid,group,axpos,... 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,... 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); 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 -1.155 0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); 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 1.155 -0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); case '<',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[0.577 0.577 -1.155 0.577]*markersize,y'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); case '>',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[-0.577 -0.577 1.155 -0.577]*markersize,y'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); end % close the marker group fprintf(fid,'\n'); end % close the scatter group fprintf(fid,'\n'); elseif strcmp(get(axchild(i),'Type'),'line') scolorname=searchcolor(id,get(axchild(i),'Color')); linestyle=get(axchild(i),'LineStyle'); linewidth=get(axchild(i),'LineWidth'); marker=get(axchild(i),'Marker'); markeredgecolor=get(axchild(i),'MarkerEdgeColor'); if ischar(markeredgecolor) switch markeredgecolor case 'none',markeredgecolorname='none'; otherwise,markeredgecolorname=scolorname; % if markeredgecolorname is 'auto' or something else set the markeredgecolorname to the line color end else markeredgecolorname=searchcolor(id,markeredgecolor); end markerfacecolor=get(axchild(i),'MarkerFaceColor'); if ischar(markerfacecolor) switch markerfacecolor case 'none',markerfacecolorname='none'; otherwise,markerfacecolorname=scolorname; % if markerfacecolorname is 'auto' or something else set the markerfacecolorname to the line color end else markerfacecolorname=searchcolor(id,markerfacecolor); end markersize=get(axchild(i),'MarkerSize')/1.5; linex = get(axchild(i),'XData'); linex = linex(:)'; % Octave stores the data in a column vector if strcmp(get(ax,'XScale'),'log') linex(linex<=0) = NaN; linex=log10(linex); end liney=get(axchild(i),'YData'); liney = liney(:)'; % Octave stores the data in a column vector if strcmp(get(ax,'YScale'),'log') liney(liney<=0) = NaN; liney=log10(liney); end linez=get(axchild(i),'ZData'); linez = linez(:)'; % Octave stores the data in a column vector if isempty(linez) linez = zeros(size(linex)); end if strcmp(get(ax,'ZScale'),'log') linez(linez<=0) = NaN; linez=log10(linez); end [x,y,z] = project(linex,liney,linez,projection); x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); markerOverlap = 0; if ~strcmp(linestyle, 'none') markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels', axpos(4))); end if ~strcmp(marker, 'none') markerOverlap = max(markerOverlap, convertunit(markersize, 'points', 'pixels', axpos(4))); end boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap]; [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement); % put a line into a group with its markers if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); else fprintf(fid,'\n', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end line2svg(fid,groupax,axpos,x,y,scolorname,linestyle,linewidth) % put the markers into a subgroup of the lines if ~strcmp(marker, 'none') % but only do it if we actually are drawing markers fprintf(fid,'\n'); switch marker case 'none'; case '.',group=group+1;circle2svg(fid,group,axpos,x,y,markersize*0.25,'none',markeredgecolorname,linewidth); case 'o',group=group+1;circle2svg(fid,group,axpos,x,y,markersize*0.75,markeredgecolorname,markerfacecolorname,linewidth); 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); 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); 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); %% Octave keeps s, d, p and h in the HandleGraphics object, for the square, diamond, pentagram, and hexagram markers, respectively -- Jakob Malm 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); 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); case {'pentagram', 'p'},group=group+1;patch2svg(fid,group,axpos,... 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,... 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); case {'hexagram', 'h'},group=group+1;patch2svg(fid,group,axpos,... 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,... 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); 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 -1.155 0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); 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 1.155 -0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); case '<',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[0.577 0.577 -1.155 0.577]*markersize,y'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); case '>',group=group+1;patch2svg(fid,group,axpos,x'*ones(1,4)+ones(length(linex),1)*[-0.577 -0.577 1.155 -0.577]*markersize,y'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); end % close the marker group fprintf(fid,'\n'); end animation2svg(fid, axchild(i)); % close the line group fprintf(fid,'\n'); elseif strcmp(get(axchild(i),'Type'),'contour') clim = get(ax,'CLim'); cmap = get(id,'Colormap'); c = get(axchild(i),'ContourMatrix'); linestyle = get(axchild(i),'LineStyle'); linewidth = get(axchild(i),'LineWidth'); edge_opacity = 1.0; face_opacity = 1.0; index = 1; while index < size(c,2) patchIndices = (1:c(2,index))+index; % Close a patch if the coordinates do not contain NaNs x = c(1,patchIndices); y = c(2,patchIndices); if (x(1) == x(end)) && (y(1) == y(end)) closed = true; else closed = false; end [x,y,z] = project(x,y,ones(1,c(2,index))*c(1,index),projection); x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); pointc = c(1,index); pointc = round((pointc-clim(1))/(clim(2)-clim(1))*(size(cmap,1)-1)+1); % Limit index to smallest or biggest color index pointc = max(pointc,1); pointc = min(pointc,size(cmap,1)); if ischar(get(axchild(i),'LineColor')) if strcmp(get(axchild(i),'LineColor'),'none') edgecolorname = 'none'; else edgecolor = c(1,index); if ~isnan(edgecolor) if strcmp(get(axchild(i),'LineColor'),'flat') % Bugfix 27.01.2008 edgecolorname = searchcolor(id,cmap(pointc,:)); else edgecolorname = searchcolor(id,edgecolor); end else edgecolorname = 'none'; end end else edgecolorname = searchcolor(id,get(axchild(i),'EdgeColor')); end if strcmp(get(axchild(i),'Fill'),'on') facecolorname = searchcolor(id,cmap(pointc,:)); end patch2svg(fid, group, axpos, x, y, facecolorname, linestyle, linewidth, edgecolorname, face_opacity, edge_opacity, closed) index = index+c(2,index)+1; end elseif strcmp(get(axchild(i),'Type'),'patch') flat_shading = 1; cmap=get(id,'Colormap'); pointc = get(axchild(i),'FaceVertexCData'); if isempty(pointc) % Workaround for octave pointc=get(axchild(i),'CData'); end % Scale color if scaled color mapping is turned on if strcmp(get(axchild(i),'CDataMapping'),'scaled') clim=get(ax,'CLim'); pointc=(pointc-clim(1))/(clim(2)-clim(1))*(size(cmap,1)-1)+1; end % Limit index to smallest or biggest color index if (all(pointc <= 1 & pointc >= 0) && length(pointc)==3) pointc=searchcolor(id, pointc); else pointc=max(pointc,1); pointc=min(pointc,size(cmap,1)); end if ~ischar(get(axchild(i),'FaceAlpha')) face_opacity = get(axchild(i),'FaceAlpha'); else face_opacity = 1.0; end if ~ischar(get(axchild(i),'EdgeAlpha')) edge_opacity = get(axchild(i),'EdgeAlpha'); else edge_opacity = 1.0; end linestyle = get(axchild(i),'LineStyle'); linewidth = get(axchild(i),'LineWidth'); marker = get(axchild(i),'Marker'); markeredgecolor=get(axchild(i),'MarkerEdgeColor'); markersize=get(axchild(i),'MarkerSize')/1.5; points=get(axchild(i),'Vertices')'; if strcmp(get(ax,'XScale'),'log') points(1,:)=log10(points(1,:)); end if strcmp(get(ax,'YScale'),'log') points(2,:)=log10(points(2,:)); end % TODO LogZ if size(points,1)==2 [x,y,z] = project(points(1,:),points(2,:),zeros(size(points(1,:))),projection); else [x,y,z] = project(points(1,:),points(2,:),points(3,:),projection); end x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); faces = get(axchild(i),'Faces'); face_index = 1:size(faces,1); if size(points,1)==3; [z,face_index]=sort(sum(z(faces(:,:)),2)); faces=faces(face_index,:); end markerOverlap = 0; if ~strcmp(linestyle, 'none') markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels', axpos(4))); end if ~strcmp(marker, 'none') markerOverlap = max(markerOverlap, convertunit(markersize, 'points', 'pixels', axpos(4))); end boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap]; [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement); if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); else fprintf(fid,'\n', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end for p = 1:size(faces,1) if ischar(get(axchild(i),'FaceColor')) if strcmp(get(axchild(i),'FaceColor'),'texturemap') facecolorname='none'; % TO DO: texture map elseif strcmp(get(axchild(i),'FaceColor'),'none') facecolorname='none'; else if size(pointc,1)==1 facecolor = pointc; elseif size(pointc,1)==size(faces,1) if strcmp(get(axchild(i),'FaceColor'),'flat') facecolor = pointc(face_index(p),:); else facecolor = pointc(face_index(p),:); cdata = pointc(face_index(p),:); % TO DO: color interpolation flat_shading = 0; end elseif size(pointc,1)==size(points,2) if strcmp(get(axchild(i),'FaceColor'),'flat') facecolor = pointc(faces(p,1),:); else facecolor = pointc(faces(p,1)); cdata = pointc(faces(p,:),:); flat_shading = 0; end else error('Unsupported color handling for patches.'); end if ~isnan(facecolor) if size(facecolor,2)==1 facecolorname = ['#' colorname(ceil(facecolor),:)]; else if strcmp(get(axchild(i),'FaceColor'),'flat') % Bugfix 27.01.2008 facecolorname = searchcolor(id,facecolor/64); else facecolorname = searchcolor(id,facecolor); end end else facecolorname='none'; end end else facecolorname = searchcolor(id,get(axchild(i),'FaceColor')); end if ischar(get(axchild(i),'EdgeColor')) if strcmp(get(axchild(i),'EdgeColor'),'none') edgecolorname = 'none'; else if size(pointc,1)==1 edgecolor = pointc; elseif size(pointc,1)==size(faces,1) edgecolor = pointc(p,:); elseif size(pointc,1)==size(points,2) if strcmp(get(axchild(i),'EdgeColor'),'flat') edgecolor = pointc(faces(p,1)); else edgecolor = pointc(faces(p,1)); % TO DO: color interpolation end else error('Unsupported color handling for patches.'); end if ~isnan(edgecolor) if size(edgecolor,2)==1 edgecolorname = ['#' colorname(ceil(edgecolor),:)]; else if strcmp(get(axchild(i),'EdgeColor'),'flat') % Bugfix 27.01.2008 edgecolorname = searchcolor(id,edgecolor/64); else edgecolorname = searchcolor(id,edgecolor); end end else edgecolorname = 'none'; end end else edgecolorname = searchcolor(id,get(axchild(i),'EdgeColor')); end % Close a patch if the coordinates do not contain NaNs if any(isnan(x)) || any(isnan(y)) closed = false; else closed = true; end if flat_shading patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), facecolorname, linestyle, linewidth, edgecolorname, face_opacity, edge_opacity, closed) else gouraud_patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), cdata, linestyle, linewidth, edgecolorname, face_opacity, edge_opacity, id) end if ~strcmp(marker, 'none') for q = 1:size(faces,2) xmarker = x(faces(p,q)); ymarker = y(faces(p,q)); % put the markers into a subgroup of the lines fprintf(fid,'\n'); if ischar(markeredgecolor) switch markeredgecolor case 'none',markeredgecolorname='none'; otherwise, % if markeredgecolorname is 'auto' or something % else set the markeredgecolorname to the line color markeredgecolorname = selectColor(axchild(i), id, p, q, points, pointc, ... colorname, faces, 'MarkerEdgeColor'); end else markeredgecolorname=searchcolor(id,markeredgecolor); end markerfacecolor=get(axchild(i),'MarkerFaceColor'); if ischar(markerfacecolor) switch markerfacecolor case 'none',markerfacecolorname='none'; otherwise, markerfacecolorname = selectColor(axchild(i), id, p, q, points, pointc, ... colorname, faces,'MarkerFaceColor'); end else markerfacecolorname=searchcolor(id,markerfacecolor); end switch marker case 'none'; case '.',group=group+1;circle2svg(fid,group,axpos,xmarker,ymarker,markersize*0.25,'none',markeredgecolorname,linewidth); case 'o',group=group+1;circle2svg(fid,group,axpos,xmarker,ymarker,markersize*0.75,markeredgecolorname,markerfacecolorname,linewidth); 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); 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); 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); %% Octave keeps s, d, p and h in the HandleGraphics object, for the square, diamond, pentagram, and hexagram markers, respectively -- Jakob Malm 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); 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); case {'pentagram', 'p'},group=group+1;patch2svg(fid,group,axpos,... 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,... 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); case {'hexagram', 'h'},group=group+1;patch2svg(fid,group,axpos,... 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,... 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); 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 -1.155 0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); 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 1.155 -0.577]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); case '<',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,4)+ones(length(linex),1)*[0.577 0.577 -1.155 0.577]*markersize,ymarker'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); case '>',group=group+1;patch2svg(fid,group,axpos,xmarker'*ones(1,4)+ones(length(linex),1)*[-0.577 -0.577 1.155 -0.577]*markersize,ymarker'*ones(1,4)+ones(length(liney),1)*[-1 1 0 -1]*markersize,markerfacecolorname,'-',linewidth,markeredgecolorname, 1, 1, true); end % close the marker group fprintf(fid,'\n'); end end end fprintf(fid,'\n'); elseif strcmp(get(axchild(i),'Type'),'surface') flat_shading = 1; cmap=get(id,'Colormap'); [faces,points,pointc,alpha]=surface2patch(axchild(i)); points=points'; % Scale color if scaled color mapping is turned on if strcmp(get(axchild(i),'CDataMapping'),'scaled') clim=get(ax,'CLim'); pointc=(pointc-clim(1))/(clim(2)-clim(1))*(size(cmap,1)-1)+1; end % Limit index to smallest or biggest color index pointc=max(pointc,1); if ~ischar(get(axchild(i),'FaceAlpha')) face_opacity = get(axchild(i),'FaceAlpha'); elseif strcmp(get(axchild(i),'FaceAlpha'),'flat') face_opacity = alpha; switch get(axchild(i),'AlphaDataMapping') case {'direct'} face_opacity = 1.0; % TODO case {'scaled'} alim=get(ax,'ALim'); face_opacity=(face_opacity-alim(1))/(alim(2)-alim(1)); case {'none'} % Clip alpha data face_opacity = min(1, face_opacity); face_opacity = max(0, face_opacity); otherwise error(['Unsupported AlphaDataMapping identifier ''' get(axchild(i),'AlphaDataMapping') '''.']); end else face_opacity = 1.0; end if ~ischar(get(axchild(i),'EdgeAlpha')) edge_opacity = get(axchild(i),'EdgeAlpha'); else edge_opacity = 1.0; end pointc=min(pointc,size(cmap,1)); linestyle=get(axchild(i),'LineStyle'); linewidth=get(axchild(i),'LineWidth'); if strcmp(get(ax,'XScale'),'log') points(1,:)=log10(points(1,:)); end if strcmp(get(ax,'YScale'),'log') points(2,:)=log10(points(2,:)); end if size(points,1)==3 if strcmp(get(ax,'ZScale'),'log') points(3,:)=log10(points(3,:)); end end if size(points,1)==3 [x,y,z] = project(points(1,:),points(2,:),points(3,:),projection); else [x,y,z] = project(points(1,:),points(2,:),zeros(size(points(1,:))),projection); end x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); face_index = 1:size(faces,1); if size(points,1)==3; [z,face_index]=sort(sum(z(faces(:,:)),2)); faces=faces(face_index,:); end markerOverlap = 0; if ~strcmp(linestyle, 'none') markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels', axpos(4))); end boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap]; [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement); if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n',clippingIdString, createId, filterString); else fprintf(fid,'\n', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end for p=1:size(faces,1) if ischar(get(axchild(i),'FaceColor')) if strcmp(get(axchild(i),'FaceColor'),'texturemap') facecolorname='none'; % TO DO: texture map elseif strcmp(get(axchild(i),'FaceColor'),'none') facecolorname='none'; else if size(pointc,1)==1 facecolor = pointc; elseif size(pointc,1)==size(faces,1) facecolor = pointc(face_index(p),:); elseif size(pointc,1)==size(points,2) if strcmp(get(axchild(i),'FaceColor'),'flat') facecolor = pointc(faces(p,1)); else facecolor = pointc(faces(p,1)); cdata = pointc(faces(p,:)); flat_shading = 0; end else error('Unsupported color handling for patches.'); end if ~isnan(facecolor) if size(facecolor,2)==1 facecolorname = ['#' colorname(ceil(facecolor),:)]; else facecolorname = searchcolor(id,facecolor); end else facecolorname='none'; end end else facecolorname = searchcolor(id,get(axchild(i),'FaceColor')); end if size(face_opacity,1)==1 face_opacity_value = face_opacity; elseif size(face_opacity,1)==size(faces,1) face_opacity_value = face_opacity(p,:); elseif size(face_opacity,1)==size(points,2) face_opacity_value = face_opacity(faces(p,1)); else error('Unsupported face alpha value handling for patches.'); end if ischar(get(axchild(i),'EdgeColor')) if strcmp(get(axchild(i),'EdgeColor'),'none') edgecolorname = 'none'; else if size(pointc,1)==1 edgecolor = pointc; elseif size(pointc,1)==size(faces,1) edgecolor = pointc(p,:); elseif size(pointc,1)==size(points,2) if strcmp(get(axchild(i),'EdgeColor'),'flat') edgecolor = pointc(faces(p,1)); else edgecolor = pointc(faces(p,1)); % TO DO: color interpolation end else error('Unsupported color handling for patches.'); end if ~isnan(edgecolor) if size(edgecolor,2)==1 edgecolorname = ['#' colorname(ceil(edgecolor),:)]; else edgecolorname = searchcolor(id,edgecolor); end else edgecolorname = 'none'; end end else edgecolorname = searchcolor(id,get(axchild(i),'EdgeColor')); end if flat_shading patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), facecolorname, linestyle, linewidth, edgecolorname, face_opacity_value, edge_opacity, false) else gouraud_patch2svg(fid, group, axpos, x(faces(p,:)), y(faces(p,:)), cdata, linestyle, linewidth, edgecolorname, face_opacity_value, edge_opacity,id) end end fprintf(fid,'\n'); elseif strcmp(get(axchild(i),'Type'),'rectangle') scolorname = searchcolor(id,get(axchild(i),'EdgeColor')); fcolorname = searchcolor(id,get(axchild(i),'FaceColor')); linewidth = get(axchild(i),'LineWidth'); position = get(axchild(i),'Position'); posx = [position(1) position(1)+position(3)]; if strcmp(get(ax,'XScale'),'log') posx(posx <= 0) = NaN; posx=log10(posx); end posy = [position(2) position(2)+position(4)]; if strcmp(get(ax,'YScale'),'log') posy(posy <= 0) = NaN; posy=log10(posy); end posz=[0 0]; linestyle = get(axchild(i),'LineStyle'); if strcmp(linestyle,'none'); scolorname = 'none'; end pattern = lineStyle2svg(linestyle, linewidth); [x,y,z] = project(posx,posy,posz,projection); x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); rect = [min(x) min(y) max(x)-min(x) max(y)-min(y)]; curvature = get(axchild(i),'Curvature'); curvature(1) = curvature(1)*rect(3)*0.5; curvature(2) = curvature(2)*rect(4)*0.5; markerOverlap = 0; if ~strcmp(linestyle, 'none') markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels', axpos(4))); end boundingBoxElement = rect + [-markerOverlap -markerOverlap 2*markerOverlap 2*markerOverlap]; [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement); % put a rectangle into a group with its markers if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); else fprintf(fid,'\n', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end fprintf(fid,'\n',... rect(1), rect(2), rect(3), rect(4), curvature(1), curvature(2), fcolorname, scolorname, linewidth, pattern); % close the rectangle group fprintf(fid,'\n'); elseif strcmp(get(axchild(i),'Type'),'text') if PLOT2SVG_globals.octave extent = [0 0 0 0]; else extent = get(axchild(i),'Extent'); end margin = get(axchild(i),'Margin'); facecolor = get(axchild(i),'BackgroundColor'); edgecolor = get(axchild(i),'EdgeColor'); linewidth = get(axchild(i),'LineWidth'); linestyle = get(axchild(i),'LineStyle'); if ischar(facecolor) if ~strcmp(facecolor,'none') error('Illegal face color for text.'); else facecolorname = 'none'; end else facecolorname = searchcolor(id, facecolor); end if ischar(edgecolor) if ~strcmp(edgecolor,'none') error('Illegal edge color for text.'); else edgecolorname = 'none'; end else edgecolorname = searchcolor(id, edgecolor); end extentx = [extent(1) extent(1)+extent(3)]; extenty = [extent(2) extent(2)+extent(4)]; extentz = [0 0]; [x,y,z] = project(extentx,extenty,extentz,projection); x = (x*axpos(3)+axpos(1))*paperpos(3); y = (1-(y*axpos(4)+axpos(2)))*paperpos(4); box = [min(x)-margin min(y)-margin max(x)-min(x)+2*margin max(y)-min(y)+2*margin]; markerOverlap = 0; if ~strcmp(linestyle, 'none') markerOverlap = max(markerOverlap, convertunit(linewidth*0.5, 'points', 'pixels', axpos(4))); end boundingBoxElement = [min(x)-markerOverlap min(y)-markerOverlap max(x)-min(x)+2*markerOverlap max(y)-min(y)+2*markerOverlap]; [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxElement); if strcmp(get(axchild(i),'Clipping'),'on') && ~PLOT2SVG_globals.octave clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); else fprintf(fid,'\n', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end if ~strcmp(edgecolorname, 'none') || ~strcmp(facecolorname, 'none') pattern = lineStyle2svg(linestyle, linewidth); fprintf(fid,'\n', ... box(1), box(2), box(3), box(4), facecolorname, edgecolorname, linewidth, pattern); end text2svg(fid,1,axpos,paperpos,axchild(i),ax,projection) fprintf(fid,'\n'); elseif strcmp(get(axchild(i),'Type'),'image') cmap=get(id,'Colormap'); pointx=get(axchild(i),'XData'); pointy=get(axchild(i),'YData'); % If the XData is a vector we only use start and stop for the image if (size(pointx, 1) > 2) || (size(pointx, 2) > 1) pointx = [pointx(1) pointx(end)]; end if (size(pointy, 1) > 2) || (size(pointy, 2) > 1) pointy = [pointy(1) pointy(end)]; end if (size(pointx, 1) > 1) && (size(pointy, 1) > 1) [x,y,z] = project(pointx,zeros(size(pointx)),zeros(size(pointx)),projection); else [x,y_dummy,z] = project(pointx,zeros(size(pointx)),zeros(size(pointx)),projection); [x_dummy,y,z] = project(zeros(size(pointy)),pointy,zeros(size(pointy)),projection); end pointc=get(axchild(i),'CData'); %pointcclass = class(pointc); % Bugfix proposed by Tom if strcmp(get(axchild(i),'CDataMapping'),'scaled') clim=get(ax,'CLim'); %pointc=(double(pointc)-clim(1))/(clim(2)-clim(1))*(size(cmap,1) - 1) + 1; % Bugfix proposed by Tom %pointcclass = 'double'; % since range is now [0->size(cmap,1)-1] % Bugfix proposed by Tom pointc=imnorm(pointc, clim(1), clim(2)); end data_aspect_ratio = get(ax,'DataAspectRatio'); if length(x) == 2 if size(pointc, 2) == 1 halfwidthx = abs(x(2) - x(1)) * data_aspect_ratio(1); else halfwidthx = abs(x(2) - x(1))/(size(pointc,2) - 1); end else halfwidthx = data_aspect_ratio(1); end if length(y) == 2 if size(pointc, 1) == 1 halfwidthy = abs(y(2) - y(1)) * data_aspect_ratio(2); else halfwidthy = abs(y(2) - y(1))/(size(pointc,1) - 1); end else halfwidthy = data_aspect_ratio(2); end if length(pointx) > 1 if xor(strcmp(get(ax,'XDir'),'reverse'), pointx(1) > pointx(2)) if ndims(pointc) < 3 pointc=fliplr(pointc); elseif ndims(pointc) == 3 for j = 1:size(pointc,3) pointc(:,:,j)=fliplr(pointc(:,:,j)); end else error('Invalid number of dimensions of data.'); end end end if length(pointy) > 1 if xor(strcmp(get(ax,'YDir'),'reverse'), pointy(1) > pointy(2)) if ndims(pointc) < 3 pointc=flipud(pointc); elseif ndims(pointc) == 3 for j = [1:size(pointc,3)] pointc(:,:,j)=flipud(pointc(:,:,j)); end else error('Invalid number of dimensions of data.'); end end end % pointc = cast(pointc,pointcclass); % Bugfix proposed by Tom % Function 'cast' is not supported by old Matlab versions %if (~isa(pointc, 'double') && ~isa(pointc, 'single')) % if strcmp(get(axchild(i),'CDataMapping'),'scaled') % pointc = double(pointc); % else % pointc = double(pointc) + 1; % end %end %if ndims(pointc) ~= 3 % pointc = max(min(round(double(pointc)),size(cmap,1)),1); %end CameraUpVector = get(ax,'CameraUpVector'); filename = [PLOT2SVG_globals.basefilename sprintf('%03d',PLOT2SVG_globals.figurenumber) '.' PLOT2SVG_globals.pixelfiletype]; PLOT2SVG_globals.figurenumber = PLOT2SVG_globals.figurenumber + 1; %if isempty(PLOT2SVG_globals.basefilepath) if isempty(PLOT2SVG_globals.basedirname) current_path = pwd; rel_path = pwd; else %current_path = PLOT2SVG_globals.basefilepath; current_path = PLOT2SVG_globals.basedirname; rel_path = PLOT2SVG_globals.reldirname; end relname = fullfile(rel_path,filename); filename = fullfile(current_path,filename); if exist(filename,'file') lastwarn(''); delete(filename); if strcmp(lastwarn,'File not found or permission denied.') error('Cannot write image file. Make sure that no image is opened in an other program.') end end if ndims(pointc) < 3 pointc = flipud(pointc); elseif ndims(pointc) == 3 for j = 1:size(pointc,3) pointc(:,:,j)=flipud(pointc(:,:,j)); end else error('Invalid number of dimensions of data.'); end if ndims(pointc) == 3 % pointc is not indexed %imwrite(pointc,fullfile(PLOT2SVG_globals.basefilepath,filename),PLOT2SVG_globals.pixelfiletype); imwrite(pointc,filename,PLOT2SVG_globals.pixelfiletype); PLOT2SVG_globals.used_dir=true; else % pointc is probably indexed pointc = max(min(round(double(pointc)),size(cmap,1)),1); %if PLOT2SVG_globals.octave % pointc = max(2, pointc); %end %imwrite(pointc,cmap,fullfile(PLOT2SVG_globals.basefilepath,filename),PLOT2SVG_globals.pixelfiletype); ncmap = size(cmap,1); if (ncmap > 256) cmap = interp1(([0:ncmap-1].')*(255/(ncmap-1)),cmap,[0:255].'); pointc = fix((pointc-1) * (255/(ncmap-1)))+1; end imwrite(pointc,cmap,filename,PLOT2SVG_globals.pixelfiletype); PLOT2SVG_globals.used_dir=true; end lx=(size(pointc,2)*halfwidthx)*axpos(3)*paperpos(3); ly=(size(pointc,1)*halfwidthy)*axpos(4)*paperpos(4); if strcmp(get(ax,'DataAspectRatioMode'),'manual') pointsx=((min(x) - halfwidthx/2)*axpos(3)+axpos(1))*paperpos(3); pointsy=(1-((max(y) + halfwidthy/2)*axpos(4)+axpos(2)))*paperpos(4); else pointsx=axpos(1)*paperpos(3); pointsy=(1-(axpos(4)+axpos(2)))*paperpos(4); end [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxAxes); if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end fprintf(fid,'\n', pointsx, pointsy, lx, ly, relname); fprintf(fid,'\n'); else fprintf(fid,'\n', createId, filterString); if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end fprintf(fid,'\n', pointsx, pointsy, lx, ly, relname); fprintf(fid,'\n'); end elseif strcmp(get(axchild(i),'Type'), 'hggroup') % handle group types (like error bars) % FIXME: they are not yet perfectly handled, there are more options % that are not used [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxAxes); if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); else fprintf(fid, '', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end group=axchild2svg(fid,id,axIdString,ax,group,paperpos,get(axchild(i), 'Children'),axpos,groupax,projection,boundingBoxAxes); fprintf(fid, ''); elseif strcmp(get(axchild(i),'Type'), 'hgtransform') if strcmpi(get(axchild(i), 'Visible'), 'on') [filterString, boundingBox] = filter2svg(fid, axchild(i), boundingBoxAxes, boundingBoxAxes); if strcmp(get(axchild(i),'Clipping'),'on') clippingIdString = clipping2svg(fid, axchild(i), ax, paperpos, axpos, projection, axIdString); fprintf(fid,'\n', createId, clippingIdString, filterString); else fprintf(fid, '', createId, filterString); end if ~isempty(filterString) % Workaround for Inkscape filter bug fprintf(fid,'\n', boundingBox(1), boundingBox(2), boundingBox(3), boundingBox(4)); end group=axchild2svg(fid,id,axIdString,ax,group,paperpos,get(axchild(i), 'Children'),axpos,groupax,projection,boundingBoxAxes); fprintf(fid, ''); end else disp([' Warning: Unhandled child type: ' get(axchild(i),'Type')]); end end function result = selectColor(axchild, id, p, q, points, pointc, colorname, faces, type) if (ischar(pointc)) result = pointc; return; end if size(pointc, 1) == 1 color = pointc; elseif size(pointc, 1) == size(faces, 1) color = pointc(p,:); elseif size(pointc, 1) == size(points, 2) if strcmp(get(axchild, type), 'flat') color = pointc(faces(p, q)); else color = pointc(faces(p, q)); % TO DO: color interpolation end else error('Unsupported color handling for patches.'); end if ~isnan(color) if size(color, 2) == 1 result = ['#' colorname(ceil(color), :)]; else if strcmp(get(axchild, type), 'flat') % Bugfix 27.01.2008 result = searchcolor(id, color / 64); else result = searchcolor(id, color); end end else result = 'none'; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % create a patch (filled area) function patch2svg(fid,group,axpos,xtot,ytot,scolorname,style,width, edgecolorname, face_opacity, edge_opacity, closed) if closed type = 'polygon'; else type = 'polyline'; end pattern = lineStyle2svg(style, width); if strcmp(style, 'none') edge_opacity = 0.0; end for i = 1:size(xtot, 1) x = xtot(i, :); y = ytot(i, :); if all(~isnan(x)) && all(~isnan(y)) for j = 1:20000:length(x) xx = x(j:min(length(x), j + 19999)); yy = y(j:min(length(y), j + 19999)); if ~strcmp(edgecolorname,'none') || ~strcmp(scolorname,'none') fprintf(fid,' <%s fill="%s" fill-opacity="%0.2f" stroke="%s" stroke-width="%0.1fpt" stroke-opacity="%0.2f" %s points="',... type, scolorname, face_opacity, edgecolorname, width, edge_opacity, pattern); fprintf(fid,'%0.3f,%0.3f ',[xx;yy]); fprintf(fid,'"/>\n'); end end else parts = find(isnan(x) + isnan(y)); if ~isempty(parts) && (parts(1) ~= 1) parts = [0 parts]; end if parts(length(parts)) ~= length(x) parts = [parts length(x) + 1]; end for j = 1:(length(parts) - 1) xx = x((parts(j)+1):(parts(j+1)-1)); yy = y((parts(j)+1):(parts(j+1)-1)); if ~strcmp(edgecolorname,'none') || ~strcmp(scolorname,'none') if ~isempty(xx) fprintf(fid,' <%s fill="%s" fill-opacity="%0.2f" stroke="%s" stroke-width="%0.1fpt" stroke-opacity="%0.2f" %s points="',... type, scolorname, face_opacity, edgecolorname, width, edge_opacity, pattern); fprintf(fid,'%0.3f,%0.3f ',[xx;yy]); fprintf(fid,'"/>\n'); end end end end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % create a patch (filled area) function gouraud_patch2svg(fid,group,axpos,xtot,ytot,cdata,style,width, edgecolorname, face_opacity, edge_opacity,id) global colorname pattern = lineStyle2svg(style, width); if strcmp(style, 'none') edge_opacity = 0.0; end for i=1:size(xtot,1) x = xtot(i,:); y = ytot(i,:); if (any(isnan(x)) || any(isnan(y))) fprintf('Warning: Found NaN in Gouraud patch.\n') else % If there are more than 2 edges always 3 edges are taken togehter % to form a triangle if length(x) > 2 for j = 3:length(x) coord = [x([1 j-1 j]);y([1 j-1 j])]; face_color = cdata(1,:); face_color2 = cdata(j-1,:); face_color3 = cdata(j,:); delta = coord(:,3)-coord(:,2); if det([delta (coord(:,1)-coord(:,2))]) ~= 0 if ~isnan(face_color) IDstring1 = createId; IDstring2 = createId; if size(face_color2,2)==1 face_color_name2 = ['#' colorname(ceil(face_color2),:)]; else face_color_name2 = searchcolor(id,face_color2/64); end if size(face_color3,2)==1 face_color_name3 = ['#' colorname(ceil(face_color3),:)]; else face_color_name3 = searchcolor(id,face_color3/64); end grad_end=(delta)*(delta'*(coord(:,1)-coord(:,2)))/(delta'*delta) + coord(:,2); if size(face_color,2)==1 face_color_name = ['#' colorname(ceil(face_color),:)]; else face_color_name = searchcolor(id,face_color/64); end fprintf(fid,'\n'); fprintf(fid,'\n',... IDstring1, coord(1,2), coord(2,2), coord(1,3), coord(2,3)); fprintf(fid,'\n',face_color_name2); fprintf(fid,'\n',face_color_name3); fprintf(fid,'\n'); fprintf(fid,'\n',... IDstring2, coord(1,1), coord(2,1), grad_end(1), grad_end(2)); fprintf(fid,'\n',face_color_name); fprintf(fid,'\n',face_color_name); fprintf(fid,'\n'); fprintf(fid,'\n'); % Open group temp_string = sprintf('%0.3f,%0.3f ',coord); fprintf(fid,'\n',face_opacity); fprintf(fid,'\n',IDstring1,temp_string); fprintf(fid,'\n',IDstring2,temp_string); % Close group fprintf(fid,'\n'); end end end end % Last we draw the line around the patch if ~strcmp(edgecolorname,'none') fprintf(fid,'\n'); end end end function patternString = lineStyle2svg(lineStyle, lineWidth) % Create the string for the line style % Note: On Matlab the line style is not identical on screen and in a png. % We will try to match with the screen format. scaling = max(1, lineWidth * 0.4); switch lineStyle case '--', patternString = sprintf('stroke-dasharray="%0.1f,%0.1f"', 8*scaling, 2*scaling); case ':', patternString = sprintf('stroke-dasharray="%0.1f,%0.1f"', 2*scaling, 2*scaling); case '-.', patternString = sprintf('stroke-dasharray="%0.1f,%0.1f,%0.1f,%0.1f"', 8*scaling, 2*scaling, 2*scaling, 2*scaling); otherwise, patternString = 'stroke-dasharray="none"'; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % create a line segment % this algorthm was optimized for large segement counts function line2svg(fid, ~, ~, x, y, scolorname, style, width, strokeopacity) SEG_SIZE = 5000; if nargin < 9 || ~isscalar(strokeopacity) strokeopacity = 1; end if ~strcmp(style,'none') pattern = lineStyle2svg(style, width); skip_pts = reshape(find(isnan(x) | isnan(y)), [],1); start_pts = [1; skip_pts+1]; end_pts = [skip_pts-1; numel(x)]; k = 1; while k <= numel(start_pts) if (end_pts(k) - start_pts(k)) > SEG_SIZE tmp_sPts = zeros(numel(start_pts)+1,1); tmp_ePts = zeros(numel(start_pts)+1,1); tmp_sPts(1:k) = start_pts(1:k); tmp_ePts(1:k-1) = end_pts(1:k-1); tmp_ePts(k) = tmp_sPts(k)+SEG_SIZE-1; tmp_sPts(k+1) = tmp_sPts(k)+SEG_SIZE-1; tmp_ePts(k+1:end) = end_pts(k:end); tmp_sPts(k+2:end) = start_pts(k+1:end); start_pts = tmp_sPts; end_pts = tmp_ePts; end k = k+1; end for j=1:numel(start_pts) xx=x(start_pts(j):end_pts(j)); yy=y(start_pts(j):end_pts(j)); fprintf(fid,' \n'); end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % create a circle function circle2svg(fid,group,axpos,x,y,radius,markeredgecolorname,markerfacecolorname,width) npts=length(x); if(size(markeredgecolorname,1)~=npts) markeredgecolorname=repmat(markeredgecolorname(1,:),npts,1); end if(size(markerfacecolorname,1)~=npts) markerfacecolorname=repmat(markerfacecolorname(1,:),npts,1); end if (length(radius)~=npts) radius=ones(npts,1)*radius(1); end for j = 1:length(x) if ~(isnan(x(j)) || isnan(y(j))) if ~strcmp(markeredgecolorname(j,:),'none') || ~strcmp(markerfacecolorname(j,:),'none') fprintf(fid,'\n',x(j),y(j),radius(j),markerfacecolorname(j,:),markeredgecolorname(j,:),width); end end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function control2svg(fid,id,ax,group,paperpos) global PLOT2SVG_globals set(ax,'Units','pixels'); %if verLessThan('matlab', '8.4.0') pos=get(ax,'Position'); %else % pos=ax.OuterPosition; %end %pict=getframe(id,pos); pict=getframe(PLOT2SVG_globals.MainFigure, pos); if isempty(pict.colormap) pict.colormap=colormap; end filename = [PLOT2SVG_globals.basefilename sprintf('%03d',PLOT2SVG_globals.figurenumber) '.' PLOT2SVG_globals.pixelfiletype]; PLOT2SVG_globals.figurenumber = PLOT2SVG_globals.figurenumber + 1; %if isempty(PLOT2SVG_globals.basefilepath) if isempty(PLOT2SVG_globals.basedirname) current_path = pwd; rel_path = pwd; else %current_path = PLOT2SVG_globals.basefilepath; current_path = PLOT2SVG_globals.basedirname; rel_path = PLOT2SVG_globals.reldirname; end relname = fullfile(rel_path,filename); filename = fullfile(current_path,filename); if exist(filename,'file') lastwarn(''); delete(filename); if strcmp(lastwarn,'File not found or permission denied.') error('Cannot write image file. Make sure that no image is opened in an other program.') end end %imwrite(pict.cdata,fullfile(PLOT2SVG_globals.basefilepath,filename),PLOT2SVG_globals.pixelfiletype); imwrite(pict.cdata,filename,PLOT2SVG_globals.pixelfiletype); PLOT2SVG_globals.used_dir=true; set(ax,'Units','normalized'); posNorm=get(ax,'Position'); posInches(1)=posNorm(1)*paperpos(3); posInches(2)=posNorm(2)*paperpos(4); posInches(3)=posNorm(3)*paperpos(3); posInches(4)=posNorm(4)*paperpos(4); lx = posInches(3); ly = posInches(4); pointsx = posInches(1); pointsy = paperpos(4)-posInches(2)-posInches(4); fprintf(fid,'\n', pointsx, pointsy, lx, ly, relname); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % create a text in the axis frame % the position of the text has to be adapted to the axis scaling function text2svg(fid,group,axpos,paperpos,id,ax,projection) global PLOT2SVG_globals; originalTextUnits=get(id,'Units'); originalTextPosition = get(id, 'Position'); if PLOT2SVG_globals.octave set(id,'Units','data'); else set(id,'Units','Data'); end textpos=get(id,'Position'); if PLOT2SVG_globals.octave xlim = get(ax, 'XLim'); ylim = get(ax, 'YLim'); zlim = get(ax, 'ZLim'); if get(ax, 'XLabel') == id textpos = textpos + [mean(xlim) ylim(1)-diff(ylim)./axpos(4)*0.06 0]; elseif get(ax, 'YLabel') == id textpos = textpos + [xlim(1)-diff(xlim)./axpos(3)*0.06 mean(ylim) 0]; elseif get(ax, 'ZLabel') == id if projection.xyplane return; end textpos = textpos + [xlim(1)-diff(xlim)./axpos(3)*0.06 0 mean(zlim)]; elseif get(ax, 'Title') == id textpos = textpos + [mean(xlim) ylim(2)+diff(ylim)./axpos(4)*0.01 0]; end end textfontsize = get(id,'FontSize'); fontsize = convertunit(get(id,'FontSize'),get(id,'FontUnits'),'points', axpos(4)); % convert fontsize to inches paperposOriginal = get(gcf,'Position'); font_color = searchcolor(id,get(id,'Color')); if strcmp(get(ax,'XScale'),'log') textpos(1) = log10(textpos(1)); end if strcmp(get(ax,'YScale'),'log') textpos(2) = log10(textpos(2)); end if strcmp(get(ax,'ZScale'),'log') textpos(3) = log10(textpos(3)); end [x,y,z] = project(textpos(1), textpos(2), textpos(3), projection); x = (x * axpos(3) + axpos(1)) * paperpos(3); y = (1 - (y * axpos(4) + axpos(2))) * paperpos(4); textvalign = get(id,'VerticalAlignment'); textalign = get(id,'HorizontalAlignment'); texttext = get(id,'String'); textrot = get(id,'Rotation'); dx = sin(textrot * pi / 180) * convertunit(fontsize * 1.2, 'points', 'pixels'); dy = cos(textrot * pi / 180) * convertunit(fontsize * 1.2, 'points', 'pixels'); lines = max(size(get(id,'String'),1),1); if size(texttext,2)~=0 j = 1; for i = 0:1:(lines - 1) if iscell(texttext) label2svg(fid, group, axpos, id, x + i * dx, y + i * dy, convertString(texttext{j}), textalign, textrot, textvalign, lines, paperpos, font_color, 0) else label2svg(fid, group, axpos, id, x + i * dx, y + i * dy, convertString(texttext(j,:)), textalign, textrot, textvalign, lines, paperpos, font_color, 0) end j = j + 1; end else label2svg(fid,group,axpos,id,x,y,'',textalign,textrot,textvalign,lines,paperpos,font_color,0) end set(id,'Units',originalTextUnits); set(id,'Position', originalTextPosition); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % adds the exponents to the axis thickmarks if needed % MATLAB itself offers no information about this exponent scaling % the exponent have therefore to be extracted from the thickmarks function exponent2svg(fid,group,axpos,paperpos,ax,axxtick,axytick,axztick) global PLOT2SVG_globals if strcmp(get(ax,'XTickLabelMode'),'auto') && strcmp(get(ax,'XScale'),'linear') fontsize=convertunit(get(ax,'FontSize'),get(ax,'FontUnits'),'points', axpos(4)); % convert fontsize to inches font_color=searchcolor(ax,get(ax,'XColor')); if PLOT2SVG_globals.octave % Octave stores XTickLabel in a cell array, which does not work nicely with str2num. --Jakob Malm axlabelx = get(ax, 'XTickLabel'); numlabels = zeros(length(axlabelx), 1); for ix = 1:length (axlabelx) numlabels(ix) = str2num(axlabelx{ix}); end else numlabels = get(ax,'XTickLabel'); if ~isempty(numlabels) numlabels = str2double(numlabels); end end labelpos = axxtick;%get(ax,'XTick'); numlabels = numlabels(:); labelpos = labelpos(:); indexnz = find(labelpos ~= 0); if (~isempty(indexnz) && ~isempty(numlabels)) if (length(indexnz) == length(numlabels) && max(indexnz) <= length(numlabels)) ratio = numlabels(indexnz)./labelpos(indexnz); else ratio = 1; end if round(log10(ratio(1))) ~= 0 && ratio(1) ~= 0 exptext = sprintf('× 10%g', -log10(ratio(1))); 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) end end end if strcmp(get(ax,'YTickLabelMode'),'auto') && strcmp(get(ax,'YScale'),'linear') fontsize=convertunit(get(ax,'FontSize'),get(ax,'FontUnits'),'points', axpos(4)); font_color=searchcolor(ax,get(ax,'YColor')); if PLOT2SVG_globals.octave % Octave stores YTickLabel in a cell array, which does not work nicely with str2num. --Jakob Malm axlabely = get(ax, 'YTickLabel'); numlabels = zeros(length(axlabely), 1); for ix = 1:length(axlabely) numlabels(ix) = str2num(axlabely{ix}); end else numlabels = get(ax,'YTickLabel'); if ~isempty(numlabels) numlabels = str2double(numlabels); end end labelpos = axytick;%get(ax,'YTick'); numlabels = numlabels(:); labelpos = labelpos(:); indexnz = find(labelpos ~= 0); if (~isempty(indexnz) && ~isempty(numlabels)) if (length(indexnz) == length(numlabels) && max(indexnz) <= length(numlabels)) ratio = numlabels(indexnz)./labelpos(indexnz); else ratio = 1; end if round(log10(ratio(1))) ~= 0 && ratio(1) ~= 0 exptext = sprintf('× 10%g', -log10(ratio(1))); 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) end end end if strcmp(get(ax,'ZTickLabelMode'),'auto') && strcmp(get(ax,'ZScale'),'linear') fontsize=convertunit(get(ax,'FontSize'),get(ax,'FontUnits'),'points', axpos(4)); font_color=searchcolor(ax,get(ax,'ZColor')); if PLOT2SVG_globals.octave % Octave stores ZTickLabel in a cell array, which does not work nicely with str2num. --Jakob Malm axlabelz = get (ax, 'ZTickLabel'); numlabels = zeros(length(axlabelz), 1); for ix = 1:length(axlabelz) numlabels(ix) = str2num(axlabelz{ix}); end else numlabels = get(ax,'ZTickLabel'); if ~isempty(numlabels) numlabels = str2double(numlabels); end end labelpos = axztick;%get(ax,'ZTick'); numlabels = numlabels(:); labelpos = labelpos(:); indexnz = find(labelpos ~= 0); if (~isempty(indexnz) && ~isempty(numlabels)) if (length(indexnz) == length(numlabels) && max(indexnz) <= length(numlabels)) ratio = numlabels(indexnz)./labelpos(indexnz); else ratio = 1; end if round(log10(ratio(1))) ~= 0 && ratio(1) ~= 0 exptext = sprintf('× 10%g', -log10(ratio(1))); 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) end end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % create a label in the figure % former versions of FrameMaker supported the commands FDY and FDX to shift the text % this commands were replaced by a shift parameter that is normed by the font size function label2svg(fid,group,axpos,id,x,y,tex,align,angle,valign,lines,paperpos,font_color,exponent) if isempty(tex) return; end textfontname=get(id,'FontName'); if strcmp(textfontname, '*') textfontname = 'Arial'; end set(id,'FontUnits','points'); textfontsize=get(id,'FontSize'); if isfield(get(id),'Interpreter') if strcmp(get(id,'Interpreter'),'tex') latex=1; elseif strcmp(get(id,'Interpreter'),'latex') latex=1; else latex=0; end else latex=1; end fontsize=convertunit(get(id,'FontSize'),get(id,'FontUnits'),'points', axpos(4)); % convert fontsize to inches fontweight = get(id,'FontWeight'); switch lower(fontweight) case 'bold', fweight = ' font-weight="bold"'; case 'light', fweight = ' font-weight="lighter"'; case 'demi', fweight = ' font-weight="lighter"'; otherwise, fweight = ''; % default 'normal' end fontangle = get(id,'FontAngle'); switch lower(fontangle) case 'italic', fangle = ' font-style="italic"'; case 'oblique', fangle = ' font-style="oblique"'; otherwise, fangle = ''; % default 'normal' end % Note: The attribute 'alignment-baseline' cannot be used as it is often % badly supported. Therfore, we use shifts. switch lower(valign) case 'top',shift=fontsize*1.18; case 'cap',shift=fontsize*0.95; case 'middle',shift = -((lines-1)/2*fontsize*1.25*1.2) + fontsize * 0.45; case 'bottom',shift = -((lines-1)*fontsize*1.25*1.2) + fontsize * -0.25; otherwise,shift=0; end switch lower(align) case 'right', anchor = 'end'; case 'center',anchor = 'middle'; otherwise,anchor = 'start'; end if iscellstr(tex) tex = strvcat(tex); elseif ~ ischar(tex) error('Invalid character type'); end if latex==1 tex=strrep(tex,'$',''); %if ~exponent % try % tex = texlabel(tex); % catch % fprintf(' Warning: Error during conversion to a latex string.'); % end %end tex=strrep(tex,'\alpha','{α}'); tex=strrep(tex,'\beta','{β}'); tex=strrep(tex,'\gamma','{γ}'); tex=strrep(tex,'\delta','{δ}'); tex=strrep(tex,'\epsilon','{ε}'); tex=strrep(tex,'\zeta','{ζ}'); tex=strrep(tex,'\eta','{η}'); tex=strrep(tex,'\theta','{θ}'); tex=strrep(tex,'\vartheta','{ϑ}'); tex=strrep(tex,'\iota','{ι}'); tex=strrep(tex,'\kappa','{κ}'); tex=strrep(tex,'\lambda','{λ}'); tex=strrep(tex,'\mu','{µ}'); tex=strrep(tex,'\nu','{ν}'); tex=strrep(tex,'\xi','{ξ}'); tex=strrep(tex,'\pi','{π}'); tex=strrep(tex,'\rho','{ρ}'); tex=strrep(tex,'\sigma','{σ}'); tex=strrep(tex,'\varsigma','{ς}'); tex=strrep(tex,'\tau','{τ}'); tex=strrep(tex,'\upsilon','{υ}'); tex=strrep(tex,'\phi','{φ}'); tex=strrep(tex,'\chi','{χ}'); tex=strrep(tex,'\psi','{ψ}'); tex=strrep(tex,'\omega','{ω}'); tex=strrep(tex,'\Gamma','{Γ}'); tex=strrep(tex,'\Delta','{Δ}'); tex=strrep(tex,'\Theta','{Θ}'); tex=strrep(tex,'\Lambda','{Λ}'); tex=strrep(tex,'\Xi','{Ξ}'); tex=strrep(tex,'\Pi','{Π}'); tex=strrep(tex,'\Sigma','{Σ}'); tex=strrep(tex,'\Tau','{Τ}'); tex=strrep(tex,'\Upsilon','{Υ}'); tex=strrep(tex,'\Phi','{Φ}'); tex=strrep(tex,'\Psi','{Ψ}'); tex=strrep(tex,'\Omega','{Ω}'); tex=strrep(tex,'\infty','{∞}'); tex=strrep(tex,'\pm','{±}'); tex=strrep(tex,'\Im','{ℑ}'); tex=strrep(tex,'\Re','{ℜ}'); tex=strrep(tex,'\approx','{≅}'); tex=strrep(tex,'\leq','{≤}'); tex=strrep(tex,'\geq','{≥}'); tex=strrep(tex,'\times','{×}'); tex=strrep(tex,'\leftrightarrow','{↔}'); tex=strrep(tex,'\leftarrow','{←}'); tex=strrep(tex,'\uparrow','{↑}'); tex=strrep(tex,'\rightarrow','{→}'); tex=strrep(tex,'\downarrow','{↓}'); tex=strrep(tex,'\circ','{º}'); tex=strrep(tex,'\propto','{∝}'); tex=strrep(tex,'\partial','{∂}'); tex=strrep(tex,'\bullet','{•}'); tex=strrep(tex,'\div','{÷}'); tex=strrep(tex,'\sum','{∑}'); tex=strrep(tex,'\ast','{∗}'); tex=strrep(tex,'\sqrt','{√}'); tex=strrep(tex,'\angle','{∠}'); tex=strrep(tex,'\wedge','{∧}'); tex=strrep(tex,'\land','{∧}'); tex=strrep(tex,'\vee','{∨}'); tex=strrep(tex,'\lor','{∨}'); tex=strrep(tex,'\cap','{∩}'); tex=strrep(tex,'\cup','{∪}'); tex=strrep(tex,'\int','{∫}'); %∴∴ tex=strrep(tex,'\sim','{∼}'); tex=strrep(tex,'\forall','{∀}'); tex=strrep(tex,'\partial','{∂}'); tex=strrep(tex,'\exists','{∃}'); tex=strrep(tex,'\emptyset','{∅}'); tex=strrep(tex,'\nabla','{∇}'); tex=strrep(tex,'\in','{∈}'); tex=strrep(tex,'\notin','{∉}'); tex=strrep(tex,'\ni','{∋}'); tex=strrep(tex,'\prod','{∏}'); tex=strrep(tex,'\cong','{≅}'); tex=strrep(tex,'\approx','{≈}'); tex=strrep(tex,'\neq','{≠}'); tex=strrep(tex,'\equiv','{≡}'); tex=strrep(tex,'\leq','{≤}'); tex=strrep(tex,'\geq','{≥}'); tex=strrep(tex,'\subset','{⊂}'); tex=strrep(tex,'\supset','{⊃}'); %⊄⊄ tex=strrep(tex,'\subseteq','{⊆}'); tex=strrep(tex,'\supseteq','{⊇}'); tex=strrep(tex,'\oplus','{⊕}'); tex=strrep(tex,'\otimes','{⊗}'); tex=strrep(tex,'\bot','{⊥}'); tex=strrep(tex,'\cdot','{⋅}'); tex=strrep(tex,'\bullet','{•}'); tex=strrep(tex,'\ldots','{…}'); tex=strrep(tex,'\prime','{′}'); % ″ double prime % ‾ oline tex=strrep(tex,'\\','{\}'); tex=strrep(tex,'\{','{{}'); tex=strrep(tex,'\}','{}}'); tex=strrep(tex,'\_','{_}'); tex=strrep(tex,'\^','{^}'); %fprintf('%s\n', tex); tex=latex2svg(tex, textfontname, textfontsize, 0); else tex=sprintf('%s', tex); end if isempty(tex) return; end if exponent tex=sprintf('10%s', 0.7*textfontsize, -0.7*textfontsize, tex); shift = shift + 0.4*fontsize; % Small correction to make it look nicer end % Note: Obviously, Matlab is using font sizes that are rounded to decimal % pt sizes. This may cause problems for very small figures. But we have to % follow due to the background size. %fprintf('%s\n', tex); fprintf(fid,' \n', x - shift * sin(-angle/180*pi), y + shift * cos(-angle/180*pi)); fprintf(fid,' \n',-angle); fprintf(fid,' ', 0, 0, textfontname, anchor, textfontsize, fweight, fangle, font_color); fprintf(fid,'%s',tex); fprintf(fid,'\n'); fprintf(fid,' \n'); fprintf(fid,' \n'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % converts LATEX strings into SVG strings function returnvalue = latex2svg(StringText, font, size, style) returnvalue = StringText; try if ~isempty(StringText) bracket = find(StringText == '{' | StringText == '}'); bracketCounter = zeros(1,length(StringText)); bracketCounter(StringText == '{') = 1; bracketCounter(StringText == '}') = -1; bracketCounter = cumsum(bracketCounter); if bracketCounter(end) ~= 0 fprintf(['Warning: Number of open and closed braces is not equal. Latex string ''' StringText ''' will not be converted.\n']); elseif any(bracketCounter < 0) fprintf(['Warning: Found a closed brace without a previously opened brace. Latex string ''' StringText ''' will not be converted.\n']); else if isempty(bracket) if any(StringText == '^' | StringText == '_' | StringText == '\' ) returnvalue = ['' singleLatex2svg(StringText) '']; % Clean up empty tspan elements % More could be done here, but with huge effort to make it % match all special cases. returnvalue = strrep(returnvalue, '>', '>'); else returnvalue = ['' StringText '']; end else returnvalue = ''; lastValidCharacter = 1; for i = 1:length(bracket) lastValidCharacterOffset = 1; if StringText(bracket(i)) == '{' % Found '{' removeCharacters = 1; localOffset = 0; if (bracket(i) > 1) if StringText(bracket(i) - 1) == '_' baselineShift = 'sub'; localFontSize = '65%%'; localOffset = -1; removeCharacters = 2; elseif StringText(bracket(i) - 1) == '^' baselineShift = 'super'; localFontSize = '65%%'; localOffset = 1; removeCharacters = 2; end end returnvalue = [returnvalue singleLatex2svg(StringText(lastValidCharacter:bracket(i) - removeCharacters)) '']; else % Found '}' returnvalue = [returnvalue singleLatex2svg(StringText(lastValidCharacter:bracket(i) - 1)) '']; end lastValidCharacter = bracket(i) + lastValidCharacterOffset; end if lastValidCharacter <= length(StringText) returnvalue = [returnvalue singleLatex2svg(StringText(lastValidCharacter:end))]; end returnvalue = [returnvalue '']; % Clean up empty tspan elements % More could be done here, but with huge effort to make it % match all special cases. returnvalue = strrep(returnvalue, '>', '>'); returnvalue = strrep(returnvalue, '>>', '>'); end end end catch ME errStr = ME.identifier; if isempty(errStr) errStr = ME.message; end fprintf(['Warning: Error ''' errStr ''' occurred during conversion. Latex string ''' StringText ''' will not be converted.\n']); end function StringText = singleLatex2svg(StringText) index = find(StringText == '_' | StringText == '^'); if ~isempty(index) if index(end) == length(StringText) % Remove orphan '_' or '^' index = index(1:end-1); end for i = length(index):-1:1 if StringText(index(i)) == '_' StringText = [StringText(1:index(i)-1) ... '' ... StringText(index(i)+1) ... '' ... StringText(index(i)+2:end)]; else StringText = [StringText(1:index(i)-1) ... '' ... StringText(index(i)+1) ... '' ... StringText(index(i)+2:end)]; end end end if ~isempty(strfind(StringText, '\bf')) StringText = strrep(StringText, '\bf', ''); end if ~isempty(strfind(StringText, '\it')) StringText = strrep(StringText, '\it', ''); end if ~isempty(strfind(StringText, '\sl')) StringText = strrep(StringText, '\sl', ''); end if ~isempty(strfind(StringText, '\rm')) StringText = strrep(StringText, '\rm', ''); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function name=searchcolor(id,value) if ischar(value) name = value; else name=repmat('#',size(value,1), 7); for i=1:size(value,1) name(i,:)=sprintf('#%02x%02x%02x',fix(value(i,1)*255),fix(value(i,2)*255),fix(value(i,3)*255)); end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function rvalue = convertunit(value, from, to, parentheight) global PLOT2SVG_globals % From SVG 1.1. Specification: % "1pt" equals "1.25px" (and therefore 1.25 user units) % "1pc" equals "15px" (and therefore 15 user units) % "1mm" would be "3.543307px" (3.543307 user units) % "1cm" equals "35.43307px" (and therefore 35.43307 user units) % "1in" equals "90px" (and therefore 90 user units) % Modification by Jonathon Harding: % MATLAB however, assumes a variable number of pixels per inch, and % assuming that the pixels match is dangerous. if nargin < 4 parentheight = 1.25; % Default end switch lower(from) % convert from input unit to points case 'pixels', rvalue = value * 72/PLOT2SVG_globals.ScreenPixelsPerInch; case 'points', rvalue = value; case 'centimeters', rvalue = value / 2.54*72; case 'inches', rvalue = value * 72; % 72 points = 1 inch case 'normalized', rvalue = value * (parentheight * 0.8); otherwise, error(['Unknown unit ' from '.']); end switch lower(to) % convert from points to specified unit case 'pixels', rvalue = rvalue * 1.25; case 'points'; % do nothing case 'centimeters', rvalue = rvalue * 2.54 / 72; case 'inches', rvalue = rvalue / 72; % 72 points = 1 inch case 'normalized', rvalue = value / (parentheight * 0.8); otherwise, error(['Unknown unit ' to '.']); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function strString=addBackSlash( strSlash) % adds a backslash at the last position of the string (if not already there) if ( strSlash(end) ~= filesep) strString = [ strSlash filesep]; else strString = strSlash; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function strExt=getFileExtension( strFileName) % returns the file extension of a filename [path, name, strExt] = fileparts( strFileName); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function StringText=convertString(StringText) if iscell(StringText) % Octave stores some strings in cell arrays. --Jakob Malm StringText = StringText{1}; end if ~isempty(StringText) StringText=strrep(StringText,'&','&'); % Do not change sequence !! StringText=strrep(StringText,'\\','\'); StringText=strrep(StringText,'<','<'); StringText=strrep(StringText,'>','>'); StringText=strrep(StringText,'"','"'); % Workaround for Firefox and Inkscape StringText=strrep(StringText,'°','°'); %StringText=strrep(StringText,'°','°'); StringText=strrep(StringText,'±','±'); StringText=strrep(StringText,'µ','µ'); StringText=strrep(StringText,'²','²'); StringText=strrep(StringText,'³','³'); StringText=strrep(StringText,'¼','¼'); StringText=strrep(StringText,'½','½'); StringText=strrep(StringText,'¾','¾'); StringText=strrep(StringText,'©','©'); StringText=strrep(StringText,'®','®'); if any(StringText > 190) StringText=strrep(StringText,'¿','¿'); StringText=strrep(StringText,'À','À'); StringText=strrep(StringText,'Á','Á'); StringText=strrep(StringText,'Â','Â'); StringText=strrep(StringText,'Ã','Ã'); StringText=strrep(StringText,'Ä','Ä'); StringText=strrep(StringText,'Å','Å'); StringText=strrep(StringText,'Æ','Æ'); StringText=strrep(StringText,'Ç','Ç'); StringText=strrep(StringText,'È','È'); StringText=strrep(StringText,'É','É'); StringText=strrep(StringText,'Ê','Ê'); StringText=strrep(StringText,'Ë','Ë'); StringText=strrep(StringText,'Ì','Ì'); StringText=strrep(StringText,'Í','Í'); StringText=strrep(StringText,'Î','Î'); StringText=strrep(StringText,'Ï','Ï'); StringText=strrep(StringText,'Ð','Ð'); StringText=strrep(StringText,'Ñ','Ñ'); StringText=strrep(StringText,'Ò','Ò'); StringText=strrep(StringText,'Ó','Ó'); StringText=strrep(StringText,'Ô','Ô'); StringText=strrep(StringText,'Õ','Õ'); StringText=strrep(StringText,'Ö','Ö'); StringText=strrep(StringText,'×','×'); StringText=strrep(StringText,'Ø','Ø'); StringText=strrep(StringText,'Ù','Ù'); StringText=strrep(StringText,'Ú','Ú'); StringText=strrep(StringText,'Û','Û'); StringText=strrep(StringText,'Ü','Ü'); StringText=strrep(StringText,'Ý','Ý'); StringText=strrep(StringText,'Þ','Þ'); StringText=strrep(StringText,'ß','ß'); StringText=strrep(StringText,'à','à'); StringText=strrep(StringText,'á','á'); StringText=strrep(StringText,'â','â'); StringText=strrep(StringText,'ã','ã'); StringText=strrep(StringText,'ä','ä'); StringText=strrep(StringText,'å','å'); StringText=strrep(StringText,'æ','æ'); StringText=strrep(StringText,'ç','ç'); StringText=strrep(StringText,'è','è'); StringText=strrep(StringText,'é','é'); StringText=strrep(StringText,'ê','ê'); StringText=strrep(StringText,'ë','ë'); StringText=strrep(StringText,'ì','ì'); StringText=strrep(StringText,'í','í'); StringText=strrep(StringText,'î','î'); StringText=strrep(StringText,'ï','ï'); StringText=strrep(StringText,'ð','ð'); StringText=strrep(StringText,'ñ','ñ'); StringText=strrep(StringText,'ò','ò'); StringText=strrep(StringText,'ó','ó'); StringText=strrep(StringText,'ô','ô'); StringText=strrep(StringText,'õ','õ'); StringText=strrep(StringText,'ö','ö'); StringText=strrep(StringText,'÷','÷'); StringText=strrep(StringText,'ø','ø'); StringText=strrep(StringText,'ù','ù'); StringText=strrep(StringText,'ú','ú'); StringText=strrep(StringText,'û','û'); StringText=strrep(StringText,'ü','ü'); StringText=strrep(StringText,'ý','ý'); StringText=strrep(StringText,'þ','þ'); StringText=strrep(StringText,'ÿ','ÿ'); end StringText=deblank(StringText); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function IdString = createId global PLOT2SVG_globals IdString = ['ID' sprintf('%06d',PLOT2SVG_globals.runningIdNumber)]; PLOT2SVG_globals.runningIdNumber = PLOT2SVG_globals.runningIdNumber + 1; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [projection, edges] = get_projection(ax,id) global PLOT2SVG_globals xc = get(ax,'CameraTarget'); phi = get(ax,'CameraViewAngle'); vi = get(ax,'View'); xi = get(ax,'XLim'); yi = get(ax,'YLim'); zi = get(ax,'ZLim'); projection.aspect_scaling = get(ax,'DataAspectRatio'); [xinfi, yinfi, zinfi] = AxesChildBounds(ax); xi(isinf(xi)) = xinfi(isinf(xi)); yi(isinf(yi)) = yinfi(isinf(yi)); zi(isinf(zi)) = zinfi(isinf(zi)); if strcmp(get(ax,'XScale'),'log') if strcmp(get(ax,'XLimMode'),'manual') && any(get(ax,'XLim') == 0) % Fix illegal scalings set by the user % -> replace all 0 with automatic calculated values (child limits) xlimM = get(ax,'XLim'); set(ax,'XLimMode','auto'); xlimA = get(ax,'XLim'); xlimM(xlimM == 0) = xlimA(xlimM == 0); set(ax,'XLimMode','manual'); set(ax,'XLim', xlimM); end xi = log10(get(ax,'XLim')); end if strcmp(get(ax,'YScale'),'log') if strcmp(get(ax,'YLimMode'),'manual') && any(get(ax,'YLim') == 0) % Fix illegal scalings set by the user % -> replace all 0 with automatic calculated values (child limits) ylimM = get(ax,'YLim'); set(ax,'YLimMode','auto'); ylimA = get(ax,'YLim'); ylimM(ylimM == 0) = ylimA(ylimM == 0); set(ax,'YLimMode','manual'); set(ax,'YLim', ylimM); end yi = log10(get(ax,'YLim')); end if strcmp(get(ax,'ZScale'),'log') if strcmp(get(ax,'ZLimMode'),'manual') && any(get(ax,'ZLim') == 0) % Fix illegal scalings set by the user % -> replace all 0 with automatic calculated values (child limits) zlimM = get(ax,'ZLim'); set(ax,'ZLimMode','auto'); zlimA = get(ax,'ZLim'); zlimM(zlimM == 0) = zlimA(zlimM == 0); set(ax,'ZLimMode','manual'); set(ax,'ZLim', zlimM); end zi = log10(get(ax,'ZLim')); end projection.xi = xi; projection.yi = yi; projection.zi = zi; xc(1) = (xc(1) - xi(1))/(xi(2)-xi(1)); xc(2) = (xc(2) - yi(1))/(yi(2)-yi(1)); xc(3) = (xc(3) - zi(1))/(zi(2)-zi(1)); if strcmp(get(ax,'XScale'),'log') x = [xi(1) xi(2) xi(1) xi(2) xi(1) xi(2) xi(1) xi(2)] - log10(projection.aspect_scaling(1)); else x = [xi(1) xi(2) xi(1) xi(2) xi(1) xi(2) xi(1) xi(2)]/projection.aspect_scaling(1); end if strcmp(get(ax,'YScale'),'log') y = [yi(1) yi(1) yi(2) yi(2) yi(1) yi(1) yi(2) yi(2)] - log10(projection.aspect_scaling(2)); else y = [yi(1) yi(1) yi(2) yi(2) yi(1) yi(1) yi(2) yi(2)]/projection.aspect_scaling(2); end if strcmp(get(ax,'ZScale'),'log') z = [zi(1) zi(1) zi(1) zi(1) zi(2) zi(2) zi(2) zi(2)] - log10(projection.aspect_scaling(3)); else z = [zi(1) zi(1) zi(1) zi(1) zi(2) zi(2) zi(2) zi(2)]/projection.aspect_scaling(3); end if PLOT2SVG_globals.octave % Get the projection angle [az, el] = view(ax); % Projection matrix from view % C = viewmtx(az, el); % NOTE: This is a subset of the MATLAB viewmtx function, as octave % does not provide such functionality % Make sure az and el are in the correct range. el = rem(rem(el+180,360)+360,360)-180; % Make sure -180 <= el <= 180 if el>90, el = 180-el; az = az + 180; elseif el<-90, el = -180-el; az = az + 180; end az = rem(rem(az,360)+360,360); % Make sure 0 <= az <= 360 % Convert from degrees to radians. az = az*pi/180; el = el*pi/180; % View transformation matrix: % Formed by composing two rotations: % 1) Rotate about the z axis -AZ radians % 2) Rotate about the x axis (EL-pi/2) radians C = [ cos(az) sin(az) 0 0 -sin(el)*sin(az) sin(el)*cos(az) cos(el) 0 cos(el)*sin(az) -cos(el)*cos(az) sin(el) 0 0 0 0 1 ]; projection.A= C; %projection.A = get(ax,'x_viewtransform'); %projection.A(3,:) = -projection.A(3,:); %projection.A(1:3,4) = 0; else if strcmp(get(ax,'Projection'),'orthographic') projection.A = viewmtx(vi(1),vi(2)); else projection.A = viewmtx(vi(1),vi(2),phi,xc); end end if (vi(1) == 0) && (mod(vi(2),90) == 0) projection.xyplane = true; else projection.xyplane = false; end axpos = get(ax,'Position'); figpos = get(id,'Position'); [m,n] = size(x); x4d = [x(:),y(:),z(:),ones(m*n,1)]'; x2d = projection.A*x4d; x2 = zeros(m,n); y2 = zeros(m,n); z2 = zeros(m,n); x2(:) = x2d(1,:)./x2d(4,:); y2(:) = x2d(2,:)./x2d(4,:); projection.ax = ax; projection.xrange = max(x2) - min(x2); projection.yrange = max(y2) - min(y2); projection.xoffset = (max(x2) + min(x2))/2; projection.yoffset = (max(y2) + min(y2))/2; if (strcmp(get(ax,'PlotBoxAspectRatioMode'),'manual') || strcmp(get(ax,'DataAspectRatioMode'),'manual')) if (projection.xrange*axpos(4)*figpos(4) < projection.yrange*axpos(3)*figpos(3)) projection.xrange = projection.yrange*axpos(3)*figpos(3)/axpos(4)/figpos(4); else projection.yrange = projection.xrange*axpos(4)*figpos(4)/axpos(3)/figpos(3); end end x2(:) = (x2d(1,:)./x2d(4,:) - projection.xoffset)/projection.xrange + 0.5; y2(:) = (x2d(2,:)./x2d(4,:) - projection.yoffset)/projection.yrange + 0.5; z2(:) = x2d(3,:); edges = [x2; y2; z2]; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [x2,y2,z2] = project(x,y,z,projection) [m,n] = size(x); if strcmp(get(projection.ax,'XDir'),'reverse') xi = projection.xi; x = (1 - (x - xi(1)) / (xi(2) - xi(1))) * (xi(2) - xi(1)) + xi(1); end if strcmp(get(projection.ax,'YDir'),'reverse') yi = projection.yi; y = (1 - (y - yi(1)) / (yi(2) - yi(1))) * (yi(2) - yi(1)) + yi(1); end if strcmp(get(projection.ax,'XScale'),'log') x = x - log10(projection.aspect_scaling(1)); else x = x/projection.aspect_scaling(1); end if strcmp(get(projection.ax,'YScale'),'log') y = y - log10(projection.aspect_scaling(2)); else y = y/projection.aspect_scaling(2); end if strcmp(get(projection.ax,'ZScale'),'log') z = z - log10(projection.aspect_scaling(3)); else z = z/projection.aspect_scaling(3); end x4d = [x(:), y(:), z(:), ones(m*n,1)]'; x2d = projection.A*x4d; x2 = zeros(m,n); y2 = zeros(m,n); z2 = zeros(m,n); x2(:) = (x2d(1,:)./x2d(4,:) - projection.xoffset)/projection.xrange + 0.5; y2(:) = (x2d(2,:)./x2d(4,:) - projection.yoffset)/projection.yrange + 0.5; z2(:) = x2d(3,:); %x = [0 1 0 1 0 1 0 1]; %y = [0 0 1 1 0 0 1 1]; %z = [0 0 0 0 1 1 1 1]; function [f, v, fvc, fva] = surface2patch(s) x = get(s, 'xdata'); y = get(s, 'ydata'); z = get(s, 'zdata'); c = get(s, 'cdata'); a = get(s, 'AlphaData'); if ~isempty(x) && ~isequal(size(x),size(z)) x = repmat(x(:)',size(z,1),1); end if ~isempty(y) && ~isequal(size(y),size(z)) y = repmat(y(:),1,size(z,2)); end [m n]= size(z); if isempty(x) [x y] = meshgrid(1:n, 1:m); end [cm cn cp] = size(c); [am an ap] = size(a); %if cm==(m-1) & cn==(n-1) % cmode = 'f'; %elseif cm==m & cn==n % cmode = 'v'; %else % cmode = ''; %end v = [x(:) y(:) z(:)]; q = [1:m*n-m-1]'; q(m:m:end) = []; fvc = reshape(c, [cm*cn cp]); fva = reshape(a, [am*an ap]); f = [q q+m q+m+1 q+1]; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Code by Jonathon Harding to detect axes child limits function [xlims, ylims, zlims] = AxesChildBounds(ax) % Get all the direct children of the axes that are not also axes (i.e. % old style legends) children = findobj(ax, '-depth', 1, '-not', 'Type', 'axes'); % Now get all children of those objects that have data we can analyze dataObjs = findobj(children, 'Type', 'line', ... '-or', 'Type', 'patch', '-or', 'Type', 'Rectangle', '-or', 'Type', 'Surface'); % Generate default limits if no objects are found xlims = [0 1]; ylims = [0 1]; zlims = [0 1]; if numel(dataObjs) == 0 return; end % Iterate through each axis one at a time axisData = {'XData', 'YData', 'ZData'}; for i=1:numel(axisData) % Set extreme bounds that will always be overridden lims = [inf -inf]; for j=1:numel(dataObjs) % For each object, get the data for the appropriate axis data = reshape(get(dataObjs(j), axisData{i}), [], 1); % Remove data that is not displayed data(isinf(data) | isnan(data)) = []; % If any data remains, update the limits if ~isempty(data) lims(1) = min(lims(1), min(data)); lims(2) = max(lims(2), max(data)); end end % If the limits are not infinite (i.e. no data found), then update % the apropriate axis limits if ~any(isinf(lims)) switch axisData{i} case 'XData' xlims = lims; case 'YData' ylims = lims; case 'ZData' zlims = lims; end end end