diff --git a/plotly/plotlyfig.m b/plotly/plotlyfig.m index 704e215d..1e88fdf0 100644 --- a/plotly/plotlyfig.m +++ b/plotly/plotlyfig.m @@ -63,6 +63,9 @@ obj.PlotOptions.TreatAs = '_'; obj.PlotOptions.Image3D = false; obj.PlotOptions.ContourProjection = false; + obj.PlotOptions.AxisEqual = false; + obj.PlotOptions.AspectRatio = []; + obj.PlotOptions.CameraEye = []; % offline options obj.PlotOptions.Offline = true; @@ -205,6 +208,15 @@ if(strcmpi(varargin{a},'TreatAs')) obj.PlotOptions.TreatAs = varargin{a+1}; end + if(strcmpi(varargin{a},'AxisEqual')) + obj.PlotOptions.AxisEqual = varargin{a+1}; + end + if(strcmpi(varargin{a},'AspectRatio')) + obj.PlotOptions.AspectRatio = varargin{a+1}; + end + if(strcmpi(varargin{a},'CameraEye')) + obj.PlotOptions.CameraEye = varargin{a+1}; + end end end @@ -280,6 +292,7 @@ for d = 1:length(obj.data) if ( ... strcmpi(obj.data{d}.type, 'scatter') || ... + strcmpi(obj.data{d}.type, 'contour') || ... strcmpi(obj.data{d}.type, 'bar') ... ) return @@ -670,8 +683,14 @@ function validate(obj) % update annotations for n = 1:obj.State.Figure.NumTexts + try + plotclass = obj.State.Plot(n).Class; + catch + plotclass = ' '; + end + try - if ~strcmpi(obj.State.Plot(dataIndex).Class, 'heatmap') + if ~strcmpi(plotclass, 'heatmap') updateAnnotation(obj,n); else obj.PlotOptions.CleanFeedTitle = false; @@ -983,7 +1002,8 @@ function delete(obj) || strcmpi(fieldname,'mesh3d') || strcmpi(fieldname,'bar') ... || strcmpi(fieldname,'scatterpolar') || strcmpi(fieldname,'barpolar') ... || strcmpi(fieldname,'scene') || strcmpi(fieldname,'layout') ... - || strcmpi(fieldname,'heatmap') ... + || strcmpi(fieldname,'heatmap') || strcmpi(fieldname,'xaxis') ... + || strcmpi(fieldname,'yaxis') ... ) fprintf(['\nWhoops! ' exception.message(1:end-1) ' in ' fieldname '\n\n']); end diff --git a/plotly/plotlyfig_aux/core/updateAxis.m b/plotly/plotlyfig_aux/core/updateAxis.m index 1d5df6b7..50524690 100644 --- a/plotly/plotlyfig_aux/core/updateAxis.m +++ b/plotly/plotlyfig_aux/core/updateAxis.m @@ -62,13 +62,22 @@ %-------------------------------------------------------------------------% +if obj.PlotOptions.AxisEqual + wh = min(axis_data.Position(3:4)); + w = wh; + h = wh; +else + w = axis_data.Position(3); + h = axis_data.Position(4); +end + %-xaxis domain-% -xaxis.domain = min([axis_data.Position(1) axis_data.Position(1)+axis_data.Position(3)],1); +xaxis.domain = min([axis_data.Position(1) axis_data.Position(1) + w],1); %-------------------------------------------------------------------------% %-yaxis domain-% -yaxis.domain = min([axis_data.Position(2) axis_data.Position(2)+axis_data.Position(4)],1); +yaxis.domain = min([axis_data.Position(2) axis_data.Position(2) + h],1); %-------------------------------------------------------------------------% diff --git a/plotly/plotlyfig_aux/core/updateData.m b/plotly/plotlyfig_aux/core/updateData.m index 833327da..bcb87fb6 100644 --- a/plotly/plotlyfig_aux/core/updateData.m +++ b/plotly/plotlyfig_aux/core/updateData.m @@ -13,6 +13,8 @@ updatePColor(obj, dataIndex); elseif strcmpi(obj.PlotOptions.TreatAs, 'polarplot') updatePolarplot(obj, dataIndex); + elseif strcmpi(obj.PlotOptions.TreatAs, 'contour3') + updateContour3(obj, dataIndex); end %-update plot based on plot call class-% @@ -148,6 +150,7 @@ if strcmpi(xaxis.type, 'category') && ... ~strcmp(obj.data{dataIndex}.type,'box') obj.data{dataIndex}.x = get(obj.State.Plot(dataIndex).AssociatedAxis,'XTickLabel'); + eval(['obj.layout.xaxis' num2str(xsource) '.autotick=true;']); end % check for yaxis dates @@ -159,6 +162,7 @@ if strcmpi(yaxis.type, 'category') && ... ~strcmp(obj.data{dataIndex}.type,'box') obj.data{dataIndex}.y = get(obj.State.Plot(dataIndex).AssociatedAxis,'YTickLabel'); + eval(['obj.layout.yaxis' num2str(xsource) '.autotick=true;']); end catch % TODO to the future diff --git a/plotly/plotlyfig_aux/core/updateFigure.m b/plotly/plotlyfig_aux/core/updateFigure.m index 24af0d00..590219ba 100644 --- a/plotly/plotlyfig_aux/core/updateFigure.m +++ b/plotly/plotlyfig_aux/core/updateFigure.m @@ -68,13 +68,22 @@ %-------------------------------------------------------------------------% +if obj.PlotOptions.AxisEqual + wh = min(figure_data.Position(3:4)); + w = wh; + h = wh; +else + w = figure_data.Position(3); + h = figure_data.Position(4); +end + %-figure width-% -obj.layout.width = figure_data.Position(3)*obj.PlotlyDefaults.FigureIncreaseFactor; +obj.layout.width = w * obj.PlotlyDefaults.FigureIncreaseFactor; %-------------------------------------------------------------------------% %-figure height-% -obj.layout.height = figure_data.Position(4)*obj.PlotlyDefaults.FigureIncreaseFactor; +obj.layout.height = h * obj.PlotlyDefaults.FigureIncreaseFactor; %-------------------------------------------------------------------------% diff --git a/plotly/plotlyfig_aux/handlegraphics/updateContour3.m b/plotly/plotlyfig_aux/handlegraphics/updateContour3.m new file mode 100644 index 00000000..9228645b --- /dev/null +++ b/plotly/plotlyfig_aux/handlegraphics/updateContour3.m @@ -0,0 +1,183 @@ +function obj = updateContour3(obj,contourIndex) + + +%-FIGURE DATA STRUCTURE-% +figure_data = get(obj.State.Figure.Handle); + +%-AXIS INDEX-% +axIndex = obj.getAxisIndex(obj.State.Plot(contourIndex).AssociatedAxis); + +%-AXIS DATA STRUCTURE-% +axis_data = get(obj.State.Plot(contourIndex).AssociatedAxis); + +%-PLOT DATA STRUCTURE- % +contour_data = get(obj.State.Plot(contourIndex).Handle); + +%-CHECK FOR MULTIPLE AXES-% +[xsource, ysource] = findSourceAxis(obj,axIndex); + +%-AXIS DATA-% +eval(['xaxis = obj.layout.xaxis' num2str(xsource) ';']); +eval(['yaxis = obj.layout.yaxis' num2str(ysource) ';']); + +%-------------------------------------------------------------------------% + +%-contour xaxis-% +obj.data{contourIndex}.xaxis = ['x' num2str(xsource)]; + +%-------------------------------------------------------------------------% + +%-contour yaxis-% +obj.data{contourIndex}.yaxis = ['y' num2str(ysource)]; + +%-------------------------------------------------------------------------% + +%-contour name-% +obj.data{contourIndex}.name = contour_data.DisplayName; + +%-------------------------------------------------------------------------% + +%-setting the plot-% +xdata = contour_data.XData; +ydata = contour_data.YData; +zdata = contour_data.ZData; + +%---------------------------------------------------------------------% + +%-contour type-% +obj.data{contourIndex}.type = 'surface'; + +%---------------------------------------------------------------------% + +%-contour x and y data +if isvector(xdata) + [xdata, ydata] = meshgrid(xdata, ydata); +end +obj.data{contourIndex}.x = xdata; +obj.data{contourIndex}.y = ydata; + +%---------------------------------------------------------------------% + +%-contour z data-% +obj.data{contourIndex}.z = zdata; + +%---------------------------------------------------------------------% + +%-setting for contour lines z-direction-% +if length(contour_data.LevelList) > 1 + zstart = contour_data.TextList(1); + zend = contour_data.TextList(end); + zsize = mean(diff(contour_data.TextList)); +else + zstart = contour_data.TextList(1) - 1e-3; + zend = contour_data.TextList(end) + 1e-3; + zsize = 2e-3; +end + +obj.data{contourIndex}.contours.z.start = zstart; +obj.data{contourIndex}.contours.z.end = zend; +obj.data{contourIndex}.contours.z.size = zsize; +obj.data{contourIndex}.contours.z.show = true; +obj.data{contourIndex}.contours.z.usecolormap = true; +obj.data{contourIndex}.contours.z.width = 2*contour_data.LineWidth; +obj.data{contourIndex}.hidesurface = true; + +%---------------------------------------------------------------------% + +%-colorscale-% +colormap = figure_data.Colormap; + +for c = 1:size((colormap),1) + col = 255*(colormap(c,:)); + obj.data{contourIndex}.colorscale{c} = {(c-1)/(size(colormap,1)-1), ['rgb(' num2str(col(1)) ',' num2str(col(2)) ',' num2str(col(3)) ')']}; +end + +%---------------------------------------------------------------------% + +%-aspect ratio-% +ar = obj.PlotOptions.AspectRatio; + +if ~isempty(ar) + if ischar(ar) + obj.layout.scene.aspectmode = ar; + elseif isvector(ar) && length(ar) == 3 + xar = ar(1); + yar = ar(2); + zar = ar(3); + end +else + + %-define as default-% + xar = max(xdata(:)); + yar = max(ydata(:)); + zar = 0.7*max([xar, yar]); +end + +obj.layout.scene.aspectratio.x = xar; +obj.layout.scene.aspectratio.y = yar; +obj.layout.scene.aspectratio.z = zar; + +%---------------------------------------------------------------------% + +%-camera eye-% +ey = obj.PlotOptions.CameraEye; + +if ~isempty(ey) + if isvector(ey) && length(ey) == 3 + obj.layout.scene.camera.eye.x = ey(1); + obj.layout.scene.camera.eye.y = ey(2); + obj.layout.scene.camera.eye.z = ey(3); + end +else + + %-define as default-% + xey = - xar; if xey>0 xfac = -0.2; else xfac = 0.2; end + yey = - yar; if yey>0 yfac = -0.2; else yfac = 0.2; end + if zar>0 zfac = 0.2; else zfac = -0.2; end + + obj.layout.scene.camera.eye.x = xey + xfac*xey; + obj.layout.scene.camera.eye.y = yey + yfac*yey; + obj.layout.scene.camera.eye.z = zar + zfac*zar; +end + +%---------------------------------------------------------------------% + +%-zerolines hidded-% +obj.layout.scene.xaxis.zeroline = false; +obj.layout.scene.yaxis.zeroline = false; +obj.layout.scene.zaxis.zeroline = false; + +%-------------------------------------------------------------------------% + +%-contour visible-% +obj.data{contourIndex}.visible = strcmp(contour_data.Visible,'on'); + +%-------------------------------------------------------------------------% + +%-contour showscale-% +obj.data{contourIndex}.showscale = false; + +%-------------------------------------------------------------------------% + +%-contour reverse scale-% +obj.data{contourIndex}.reversescale = false; + +%-------------------------------------------------------------------------% + +%-contour showlegend-% + +leg = get(contour_data.Annotation); +legInfo = get(leg.LegendInformation); + +switch legInfo.IconDisplayStyle + case 'on' + showleg = true; + case 'off' + showleg = false; +end + +obj.data{contourIndex}.showlegend = showleg; + +%-------------------------------------------------------------------------% + +end diff --git a/plotly/plotlyfig_aux/handlegraphics/updateContourgroup.m b/plotly/plotlyfig_aux/handlegraphics/updateContourgroup.m index 255e472e..d7f86aec 100644 --- a/plotly/plotlyfig_aux/handlegraphics/updateContourgroup.m +++ b/plotly/plotlyfig_aux/handlegraphics/updateContourgroup.m @@ -79,113 +79,71 @@ xdata = contour_data.XData; ydata = contour_data.YData; zdata = contour_data.ZData; - -if isvector(zdata) - - %-contour type-% - obj.data{contourIndex}.type = 'contour'; - %-contour x data-% - if ~isvector(x) - obj.data{contourIndex}.xdata = xdata(1,:); - else - obj.data{contourIndex}.xdata = xdata; - end +%-------------------------------------------------------------------------% - %-contour y data-% - if ~isvector(y) - obj.data{contourIndex}.ydata = ydata'; - else - obj.data{contourIndex}.ydata = ydata'; - end - - %-contour z data-% - obj.data{contourIndex}.z = zdata; - +%-contour type-% +obj.data{contourIndex}.type = 'contour'; + +%-------------------------------------------------------------------------% + +%-contour x data-% +if ~isvector(xdata) + obj.data{contourIndex}.x = xdata(1,:); else - - %-contour type-% - obj.data{contourIndex}.type = 'surface'; - - %-contour x and y data - if isvector(xdata) - [xdata, ydata] = meshgrid(xdata, ydata); - end obj.data{contourIndex}.x = xdata; - obj.data{contourIndex}.y = ydata; - - %-contour z data-% - obj.data{contourIndex}.z = zdata; - - %-setting for contour lines z-direction-% - if length(contour_data.LevelList) > 1 - zstart = contour_data.LevelList(1); - zend = contour_data.LevelList(end); - zsize = mean(diff(contour_data.LevelList)); - else - zstart = contour_data.LevelList(1) - 1e-3; - zend = contour_data.LevelList(end) + 1e-3; - zsize = 2e-3; - end - l = 30; - obj.data{contourIndex}.contours.z.start = zstart; - obj.data{contourIndex}.contours.z.end = zend; - obj.data{contourIndex}.contours.z.size = zsize; - obj.data{contourIndex}.contours.z.show = true; - obj.data{contourIndex}.contours.z.usecolormap = true; - obj.data{contourIndex}.contours.z.width = contour_data.LineWidth; - obj.data{contourIndex}.hidesurface = true; - end %-------------------------------------------------------------------------% -if isvector(zdata) - - %-contour x type-% +%-contour y data-% +if ~isvector(ydata) + obj.data{contourIndex}.y = ydata(:, 1); +else + obj.data{contourIndex}.y = ydata'; +end - obj.data{contourIndex}.xtype = 'array'; +%-------------------------------------------------------------------------% - %-------------------------------------------------------------------------% +%-contour z data-% +obj.data{contourIndex}.z = zdata; - %-contour y type-% +%-------------------------------------------------------------------------% - obj.data{contourIndex}.ytype = 'array'; - -end +%-contour x type-% + +obj.data{contourIndex}.xtype = 'array'; %-------------------------------------------------------------------------% -%-contour visible-% +%-contour y type-% -obj.data{contourIndex}.visible = strcmp(contour_data.Visible,'on'); +obj.data{contourIndex}.ytype = 'array'; %-------------------------------------------------------------------------% -%-contour showscale-% -obj.data{contourIndex}.showscale = false; +%-zauto-% +obj.data{contourIndex}.zauto = false; %-------------------------------------------------------------------------% -if isvector(zdata) - %-zauto-% - obj.data{contourIndex}.zauto = false; +%-zmin-% +obj.data{contourIndex}.zmin = axis_data.CLim(1); - %-------------------------------------------------------------------------% +%-------------------------------------------------------------------------% - %-zmin-% - obj.data{contourIndex}.zmin = axis_data.CLim(1); +%-zmax-% +obj.data{contourIndex}.zmax = axis_data.CLim(2); - %-------------------------------------------------------------------------% +%-------------------------------------------------------------------------% - %-zmax-% - obj.data{contourIndex}.zmax = axis_data.CLim(2); -end +%-autocontour-% +obj.data{contourIndex}.autocontour = false; -%-------------------------------------------------------------------------% +%---------------------------------------------------------------------% -%-colorscale (ASSUMES PATCH CDATAMAP IS 'SCALED')-% -colormap = figure_data.Colormap; +%-colorscale-% +colormap = axis_data.Colormap; for c = 1:size((colormap),1) col = 255*(colormap(c,:)); @@ -194,86 +152,102 @@ %-------------------------------------------------------------------------% -%-contour reverse scale-% -obj.data{contourIndex}.reversescale = false; +%-contour contours-% + +%-coloring-% +switch contour_data.Fill + case 'off' + obj.data{contourIndex}.contours.coloring = 'lines'; + case 'on' + obj.data{contourIndex}.contours.coloring = 'fill'; +end %-------------------------------------------------------------------------% -if isvector(zdata) - - %-autocontour-% - obj.data{contourIndex}.autocontour = false; - +%-contour levels-% +if length(contour_data.LevelList) > 1 + cstart = contour_data.TextList(1); + cend = contour_data.TextList(end); + csize = mean(diff(contour_data.TextList)); +else + cstart = contour_data.TextList(1) - 1e-3; + cend = contour_data.TextList(end) + 1e-3; + csize = 2e-3; end +%-start-% +obj.data{contourIndex}.contours.start = cstart; + +%-end-% +obj.data{contourIndex}.contours.end = cend; + +%-step-% +obj.data{contourIndex}.contours.size = csize; + %-------------------------------------------------------------------------% -if isvector(zdata) - - %-contour contours-% - - %-coloring-% - switch contour_data.Fill - case 'off' - obj.data{contourIndex}.contours.coloring = 'lines'; - case 'on' - obj.data{contourIndex}.contours.coloring = 'fill'; +%-contour line setting-% +if(~strcmp(contour_data.LineStyle,'none')) + + %-contour line colour-% + if isnumeric(contour_data.LineColor) + col = 255*contour_data.LineColor; + obj.data{contourIndex}.line.color = ['rgb(' num2str(col(1)) ',' num2str(col(2)) ',' num2str(col(3)) ')']; + else + obj.data{contourIndex}.line.color = 'rgba(0,0,0,0)'; end - %-start-% - obj.data{contourIndex}.contours.start = contour_data.TextList(1); + %-contour line width-% + obj.data{contourIndex}.line.width = 1.5 * contour_data.LineWidth; + + %-contour line dash-% + switch contour_data.LineStyle + case '-' + LineStyle = 'solid'; + case '--' + LineStyle = 'dash'; + case ':' + LineStyle = 'dot'; + case '-.' + LineStyle = 'dashdot'; + end - %-end-% - obj.data{contourIndex}.contours.end = contour_data.TextList(end); + obj.data{contourIndex}.line.dash = LineStyle; + + %-contour smoothing-% + obj.data{contourIndex}.line.smoothing = 0; + +else + + %-contours showlines-% + obj.data{contourIndex}.contours.showlines = false; - %-step-% - obj.data{contourIndex}.contours.size = diff(contour_data.TextList(1:2)); - end %-------------------------------------------------------------------------% -if isvector(zdata) - if(~strcmp(contour_data.LineStyle,'none')) - - %-contour line colour-% - if isnumeric(contour_data.LineColor) - col = 255*contour_data.LineColor; - obj.data{contourIndex}.line.color = ['rgb(' num2str(col(1)) ',' num2str(col(2)) ',' num2str(col(3)) ')']; - else - obj.data{contourIndex}.line.color = 'rgba(0,0,0,0)'; - end - - %-contour line width-% - obj.data{contourIndex}.line.width = contour_data.LineWidth; - - %-contour line dash-% - switch contour_data.LineStyle - case '-' - LineStyle = 'solid'; - case '--' - LineStyle = 'dash'; - case ':' - LineStyle = 'dot'; - case '-.' - LineStyle = 'dashdot'; - end - - obj.data{contourIndex}.line.dash = LineStyle; - - %-contour smoothing-% - obj.data{contourIndex}.line.smoothing = 0; - - else +%-contour visible-% +obj.data{contourIndex}.visible = strcmp(contour_data.Visible,'on'); - %-contours showlines-% - obj.data{contourIndex}.contours.showlines = false; +%-------------------------------------------------------------------------% - end +%-show contour labels-% +if strcmpi(contour_data.ShowText, 'on') + obj.data{contourIndex}.contours.showlabels = true; end %-------------------------------------------------------------------------% +%-contour showscale-% +obj.data{contourIndex}.showscale = true; + +%-------------------------------------------------------------------------% + +%-contour reverse scale-% +obj.data{contourIndex}.reversescale = false; + +%-------------------------------------------------------------------------% + %-contour showlegend-% leg = get(contour_data.Annotation); diff --git a/plotly/plotlyfig_aux/handlegraphics/updateFunctionContour.m b/plotly/plotlyfig_aux/handlegraphics/updateFunctionContour.m index 043944de..04412450 100644 --- a/plotly/plotlyfig_aux/handlegraphics/updateFunctionContour.m +++ b/plotly/plotlyfig_aux/handlegraphics/updateFunctionContour.m @@ -133,14 +133,27 @@ obj.data{contourIndex}.contours.coloring = 'fill'; end +%-------------------------------------------------------------------------% + +%-contour levels-% +if length(contour_data.LevelList) > 1 + cstart = contour_data.LevelList(1); + cend = contour_data.LevelList(end); + csize = mean(diff(contour_data.LevelList)); +else + cstart = contour_data.LevelList(1) - 1e-3; + cend = contour_data.LevelList(end) + 1e-3; + csize = 2e-3; +end + %-start-% -obj.data{contourIndex}.contours.start = contour_data.LevelList(1); +obj.data{contourIndex}.contours.start = cstart; %-end-% -obj.data{contourIndex}.contours.end = contour_data.LevelList(end); +obj.data{contourIndex}.contours.end = cend; %-step-% -obj.data{contourIndex}.contours.size = contour_data.LevelStep; +obj.data{contourIndex}.contours.size = csize; %-------------------------------------------------------------------------% @@ -199,4 +212,18 @@ %-------------------------------------------------------------------------% +%-axis layout-% +t = 'linear'; +eval(['obj.layout.xaxis' num2str(xsource) '.type=t;']); +eval(['obj.layout.xaxis' num2str(xsource) '.autorange=true;']); +eval(['obj.layout.xaxis' num2str(xsource) '.ticktext=axis_data.XTickLabel;']); +eval(['obj.layout.xaxis' num2str(xsource) '.tickvals=axis_data.XTick;']); + +eval(['obj.layout.yaxis' num2str(xsource) '.type=t;']); +eval(['obj.layout.yaxis' num2str(xsource) '.autorange=true;']); +eval(['obj.layout.yaxis' num2str(xsource) '.ticktext=axis_data.YTickLabel;']); +eval(['obj.layout.yaxis' num2str(xsource) '.tickvals=axis_data.YTick;']); + +%-------------------------------------------------------------------------% + end diff --git a/plotly/plotlyfig_aux/helpers/extractAxisData.m b/plotly/plotlyfig_aux/helpers/extractAxisData.m index a42a4721..201d883f 100644 --- a/plotly/plotlyfig_aux/helpers/extractAxisData.m +++ b/plotly/plotlyfig_aux/helpers/extractAxisData.m @@ -223,7 +223,7 @@ %-range (overwrite)-% axis.autorange = true; %-axis autotick-% - axis.autotick = true; + % axis.autotick = true; end end end diff --git a/plotly/plotlyfig_aux/helpers/handleFileName.m b/plotly/plotlyfig_aux/helpers/handleFileName.m index 9967dca1..58922cf7 100644 --- a/plotly/plotlyfig_aux/helpers/handleFileName.m +++ b/plotly/plotlyfig_aux/helpers/handleFileName.m @@ -7,6 +7,11 @@ function handleFileName(obj) str = get(obj.State.Text(t).Handle,'String'); interp = get(obj.State.Text(t).Handle,'Interpreter'); obj.PlotOptions.FileName = parseString(str,interp); + + % untitle.html if \text exist (special chars) + if ~isempty(strfind(obj.PlotOptions.FileName, '\text')) + obj.PlotOptions.FileName = 'untitled'; + end end end end