Bubbleplot function from file exchange: overlapping text and positioning
1 次查看(过去 30 天)
显示 更早的评论
Hello all,
I'm having a hard time figuring out how to place well the data point text on the scatter plot ploted using this function:
I want the text to be at the limit of the marker (circles by default) but I don't figure out a way of doing so. I tried setting the axis units to a different type but nothing.
function [lh, th] = bubbleplot(x, y, z, siz, col, shape, varargin)
error(nargchk(2,10,nargin,'struct'));
% Default z
if nargin < 3
z = [];
end
% Default size
if nargin < 4 || isempty(siz)
siz = 8;
end
if nargin < 5 || isempty(col)
col = z;
end
if nargin < 6 || isempty(shape)
shape = 'o';
end
p = inputParser;
p.addOptional('Text',{},@(x)iscellstr(x)||(ischar(x)&&size(x,1)>1)||(~ischar(x)&&length(x)>1));
p.addParamValue('ShowText',true);
p.addParamValue('FontSize',8);
p.addParamValue('Alignment', 'left');
p.addParamValue('MarkerSizeLimits',[3 20]);
p.addParamValue('ColorMap',@cool);
p.parse(varargin{:});
desctext = p.Results.Text;
showText = p.Results.ShowText;
if isempty(desctext), showText = false; end
fontSize = p.Results.FontSize;
alignment = p.Results.Alignment;
colmapfun = p.Results.ColorMap;
markerSizeLimits = p.Results.MarkerSizeLimits;
%% Determine marker colors
if ischar(colmapfun)
colmapfun = str2func(colmapfun);
elseif isnumeric(colmapfun)
colmapfun = @(x)colmapfun(1:min(x,end),:);
end
if isempty(col)
col = zeros(size(x));
end
[uniqueCols, gar, colInd] = unique(col);
if isinteger(col) || isa(col,'categorical') || iscell(col) || length(uniqueCols)<=.1*length(col) || all(round(col)==col) % Is col categorical
% Generate a colormap with one level per unique entry in col
colmap = colmapfun(length(uniqueCols));
else
% Scale the color values to span the colormap
colmap = colmapfun(256);
mx = max(col);
n = min(col);
if mx == n, mx = n + 1; end
colInd = (col-n)/(mx-n)*(size(colmap,1)-1)+1;
end
try
color = colmap(round(colInd),:);
catch %#ok<CTCH>
error('The custom colormap must have at least %d levels', max(colInd));
end
%% Determine marker shape
if ischar(shape)
markertype = repmat(shape(1),size(x));
else
markerseq = 'osd^><vph.*+x';
[uniqueShapes, gar, shapeInd] = unique(shape);
if length(uniqueShapes)>length(markerseq)
error('BubblePlot can only support 13 unique shapes');
end
markertype = markerseq(shapeInd);
end
%% Determine marker size
if isscalar(siz)
siz = repmat(siz, size(x));
markersize = siz;
else % Map the siz variable to a markersize between a minimum and maximum
minsize = markerSizeLimits(1);
maxsize = markerSizeLimits(2);
markersize = (siz - min(siz))/(max(siz)-min(siz))*(maxsize - minsize)+minsize;
end
%% Clean up data - handle NaNs
markersize(isnan(markersize)) = .01; % These will not be drawn as regular markers, just pixel points
%isnan(x) | isnan(y) | isnan(z) | isnan(col) |
%% Plot data
% Create structure to store original data in every graphics object (for
% subsequent retrieval, eg: with data tip)
pointData = struct('x',num2cell(x),'y',num2cell(y),'siz',num2cell(siz),'col',num2cell(col),...
'shape',num2cell(shape));
if nargin > 6 && ~isempty(desctext)
if ~iscellstr(desctext)
desctext = cellstr(desctext);
end
[pointData.text] = desctext{:};
end
if isempty(z)
plotfun = @plot;
%plotfun = @patch;
%zarg = {color(1,:)};
zarg = {};
else
plotfun = @plot3;
zarg = {z(1)};
zdata = num2cell(z);
[pointData.z] = zdata{:};
end
lh = zeros(1,length(x)); % Line Handles
lh(1) = customPlot(plotfun, pointData(1), color(1,:), markersize(1), markertype(1), x(1), y(1), zarg{:});
for i = 2:length(lh)
if isempty(z), zarg = {}; else zarg = {z(i)}; end
%if isempty(z), zarg = {color(i,:)}; else zarg = {z(i)}; end
lh(i) = customPlot(@line, pointData(i), color(i,:), markersize(i), markertype(i), x(i), y(i), zarg{:});
%lh(i) = customPlot(@patch, pointData(i), color(i,:), markersize(i), markertype(i), x(i), y(i), zarg{:});
end
if showText
hAxes = get(lh(1),'Parent');
offset = diff(get(hAxes,'Ylim'))*.01;
if isempty(z)
z = zeros(size(x));
end
th = text(x, y-offset, z, desctext, 'Fontsize', fontSize, 'HorizontalAlignment', alignment);
lims = get(hAxes,{'XLim','YLim','ZLim'});
lims = vertcat(lims{:});
factor = fontSize.*diff(lims,[],2);
addlistener(hAxes,{'XLim','YLim'},'PostSet',@(obj,evdata)resizeText(hAxes, th, y, factor));
%addlistener(get(hAxes,'Parent'),'Resize',@(obj,evdata)resizeText(hAxes, th));
else
th = [];
end
function lh = customPlot(funh, pointData, c, siz, markertype, varargin)
lh = funh(varargin{:});
set(lh, 'Marker', markertype,...
'LineStyle', 'none', 'Color', c, ...
'MarkerFaceColor', c, ...
'MarkerEdgeColor', [0 0 0], 'MarkerSize', siz,...
'UserData', struct('Point',pointData));
% lh = patch('XData',x(i),'YData', y(i), 'ZData', z(i), 'Marker', 'o',...
% 'LineStyle', 'none', 'CData', color, 'MarkerFaceColor', c, ...
% 'MarkerEdgeColor', [0 0 0], 'MarkerSize', siz2(i), 'FaceAlpha', .4, 'EdgeAlpha', .2, ...
% 'UserData', data);
function resizeText(hAxes, hText, y, factor) %#ok<*INUSD>
lims = get(hAxes,{'XLim','YLim','ZLim'});
lims = vertcat(lims{:});
% Uncomment following to update fontsize
% newfs = min([factor(1:2)./diff(lims(1:2,:),[],2) ; 24]);
% set(hText,'FontSize',newfs);
% Update position
offset = diff(get(hAxes,'Ylim'))*.01;
p = get(hText,'Position');
p = vertcat(p{:});
outofbounds = any(bsxfun(@gt,p,lims(:,2)') | bsxfun(@lt,p,lims(:,1)'), 2);
set(hText(outofbounds),'Visible','off');
set(hText(~outofbounds),'Visible','on');
% Adjust offsets
p(:,2) = y - offset;
for i = 1:length(p)
set(hText(i),'Position',p(i,:));
end
I have some points with the same coordinates and the text associated with these points are overlapping.
I added a function to re-set the text position using the text handle :
function fitText(hText,mrkrSize)
for i=1:length(hText)
disp(hText(1).Position)
disp(mrkrSize(1))
[newposx, newposy, newposz]=pos(hText(i).Position, mrkrSize(i));
set(hText(i),'Position',[newposx, newposy, newposz]);
end
function [a,b,c] = pos(posX0,mrkrsize)
a = posX0(1)+mrkrsize/10;
b = posX0(2)+mrkrsize/10;
c = posX0(3);
Do you have any clue of doing it properly?
thanking you in advance
1 个评论
darova
2019-11-8
Can you show your original image and the picture your want to achieve? Maybe simple drawing?
回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Graphics Object Programming 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!