Order area plots by their visible area, to maximize displayed information

Viewed 4005

I'm trying to plot a series of area plots in front of each others (not stacked). The problem is they sometimes hide each other. Take a look at this example:

clc; close all; clear variables;
%% generate some data
p = {[0 1 0 1.1];
    [0 1 0 1];
    [0 1 0 0.2];
    [0.1 0.9 0 1.1]};
t = linspace(0, 2*pi);
y = cell2mat(cellfun(@(p) abs(p(1) + p(2)*sin(p(3)+p(4)*t)), p, 'UniformOutput', 0));

%% area plots without any order
n = size(p, 1);
C = lines(n);
h(1) = figure; hold on
for i=1:n
    area(t, y(i, :), 'facecolor', C(i, :))
end

enter image description here

I tried to sort surfaces by their area to get a better result:

%% order surfaces by their area
integral = sum(y, 2);
[~, order] = sort(integral, 'descend');
h(2) = figure; hold on
for i=1:n
    area(t, y(order(i), :), 'facecolor', C(order(i), :))
end

enter image description here

But the result is not satisfactory yet. I think the objective here is to maximize the area of least visible surface.

%% order surfaces by VISIBLE area
betterOrderIMO = [3 1 4 2 ];
h(3) = figure; hold on
for i=1:n
    area(t, y(betterOrderIMO(i), :), 'facecolor', C(betterOrderIMO(i), :))
end

%% test visible area
N = zeros(3, n);
C = floor(C*256);
for i=1:3
    f = getframe(h(i));
    I = (f.cdata);
    for j=1:n
        N(i, j) = sum(sum(I(:, :, 1)==C(j, 1)& I(:, :, 2)==C(j, 2)&I(:, :, 3)==C(j, 3)));
    end
end
min(N, [], 2)

enter image description here

ans = -> No. of pixels of the least visible surface

    2363 -> not ordered
    3034 -> ordered by area
    4146 -> ordered manually

I can run an optimization (e.g. ga), but that seems overkill.
So are there any other options to get the bast order of a series of area plots, that maximizes the area of least visible plot?

1 Answers

It appears that your problem is to display a lot of signals/functions at the same time, based on your comments. How about you use a 3-dimensional perspective?

%% generate some data
p = {[0 1 0 1.1];
    [0 1 0 1];
    [0 1 0 0.2];
    [0.1 0.9 0 1.1]};
t = linspace(0, 2*pi);
y = cell2mat(cellfun(@(p) abs(p(1) + p(2)*sin(p(3)+p(4)*t)), p, 'UniformOutput', 0));

%% area plots without any order
n = size(p, 1);
C = lines(n);
h(1) = figure; hold on
for i=1:n
    patch( i*ones([1 numel(t)+2]), [t(1) t t(end)], [0 y(i,:) 0], C(i,:) );
end
view(3);
grid on;

Three-dimensional view, filled faces.

You may want to replace the tick labels along the x axis with something more meaningful.

Another option would be this:

%% generate some data
p = {[0 1 0 1.1];
    [0 1 0 1];
    [0 1 0 0.2];
    [0.1 0.9 0 1.1]};
t = linspace(0, 2*pi);
y = cell2mat(cellfun(@(p) abs(p(1) + p(2)*sin(p(3)+p(4)*t)), p, 'UniformOutput', 0));

%% area plots without any order
n = size(p, 1);
C = lines(n);
h(1) = figure;
h_patch=waterfall( [t(1) t t(end)], 1:n, [zeros([n 1]) y zeros([n 1])], (1:n).'.*ones([n numel(t)+2]) );
colormap(C);
set(h_patch,'FaceColor','none');
set(h_patch,'LineWidth',2);
view(-15,75);

Three-dimensional view, transparent faces.

Related