Bubbleplot function from file exchange: overlapping text and positioning
1 Ansicht (letzte 30 Tage)
Ältere Kommentare anzeigen
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 Kommentar
darova
am 8 Nov. 2019
Can you show your original image and the picture your want to achieve? Maybe simple drawing?
Antworten (0)
Siehe auch
Kategorien
Mehr zu Graphics Object Programming finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!