Graphiques de style xkcd dans MATLAB


Answers

Plutôt que de ré-implémenter toutes les différentes fonctions de traçage, j'ai voulu créer un outil générique qui pourrait convertir n'importe quel tracé existant en un tracé de style xkcd.

Cette approche signifie que vous pouvez créer des tracés et les styler en utilisant les fonctions standard de MATLAB , puis lorsque vous avez terminé, vous pouvez ensuite rendre le tracé dans un style xkcd tout en préservant le style général de l'intrigue.

Exemples

Terrain

Bar et Terrain

Boîte et terrain

Comment ça marche

La fonction fonctionne en itérant sur les enfants d'un axe. Si les enfants sont de type line ou patch ils les déforment légèrement. Si l'enfant est de type hggroup il itère sur les sous-enfants du hggroup . J'ai prévu de prendre en charge d'autres types de tracés, tels que l' image , mais on ne sait pas quelle est la meilleure façon de déformer l'image pour avoir un style xkcd.

Enfin pour m'assurer que les distorsions semblent uniformes (c'est-à-dire que les lignes courtes ne sont pas plus distordues que les lignes longues), je mesure la longueur de la ligne en pixels et ensuite l'échantillon proportionnel à sa longueur. J'ajoute ensuite du bruit à chaque Nième échantillon qui produit des lignes ayant plus ou moins la même distorsion.

Le code

Plutôt que de coller plusieurs centaines de lignes de code, je vais juste lier à un sens de la source . De plus, le code source et le code pour générer les exemples ci-dessus sont disponibles gratuitement GitHub .

Comme vous pouvez le voir à partir des exemples, il ne déforme pas encore les axes eux-mêmes bien que je prévois de mettre en œuvre dès que je trouverai la meilleure façon de le faire.

Question

Des gens talentueux ont donc trouvé comment créer des graphes de style xkcd dans Mathematica , dans LaTeX , dans Python et dans R.

Comment peut-on utiliser MATLAB pour produire une intrigue qui ressemble à celle ci-dessus?

Ce que j'ai essayé

J'ai créé des lignes ondulées, mais je n'ai pas pu obtenir d'axes ondulés. La seule solution que je pensais était de les écraser avec des lignes ondulées, mais je veux être en mesure de changer les axes réels. Je ne pouvais pas non plus faire fonctionner la police Humour, le code utilisé était:

 annotation('textbox',[left+left/8 top+0.65*top 0.05525 0.065],...
'String',{'EMBARRASSMENT'},...
'FontSize',24,...
'FontName','Humor',...
'FitBoxToText','off',...
'LineStyle','none');

Pour la ligne wiggly, j'ai expérimenté avec l'ajout d'un petit bruit aléatoire et de lissage:

 smooth(0.05*randn(size(x)),10)

Mais je ne pouvais pas faire apparaître le fond blanc autour d'eux quand ils se croisent ...




OK alors, voici ma tentative moins-brutale mais-encore-pas-encore-là-encore:

%# init
%# ------------------------

noise = @(x,A) A*randn(size(x));
ns    = @(x,A) A*ones(size(x));


h = figure(2); clf, hold on
pos = get(h, 'position');
set(h, 'position', [pos(1:2) 800 450]);


blackline = {
    'k', ...
    'linewidth', 2};
axisline = {
    'k', ...
    'linewidth', 3};

textprops = {
    'fontName','Comic Sans MS',...
    'fontSize', 14,...
    'lineWidth',3};


%# Plot data
%# ------------------------
x  = 1:0.1:10;

y0 = sin(x).*exp(-x/30) + 3;
y1 = sin(x).*exp(-x/3) + 3;
y2 = 3*exp(-(x-7).^6/.05) + 1;

y0 = y0 + noise(x, 0.01);
y1 = y1 + noise(x, 0.01);
y2 = y2 + noise(x, 0.01);

%# plot
plot(x,y0, 'color', [0.7 0.7 0.7], 'lineWidth',3);

plot(x,y1, 'w','lineWidth',7);
plot(x,y1, 'b','lineWidth',3);

plot(x,y2, 'w','lineWidth',7);
plot(x,y2, 'r','lineWidth',3);




%# text
%# ------------------------
ll(1) = text(1.3, 4.2,...
    {'Walking back to my'
    'front door at night:'});

ll(2) = text(5, 0.7, 'yard');
ll(3) = text(6.2, 0.7, 'steps');
ll(4) = text(7, 0.7, 'door');
ll(5) = text(8, 0.7, 'inside');

set(ll, textprops{:});


%# arrows & lines
%# ------------------------

%# box around "walking back..."
xx = 1.2:0.1:3.74;
yy = ns(xx, 4.6) + noise(xx, 0.007);
plot(xx, yy, blackline{:})

xx = 1.2:0.1:3.74;
yy = ns(xx, 3.8) + noise(xx, 0.007);
plot(xx, yy, blackline{:})

yy = 3.8:0.1:4.6;
xx = ns(yy, 1.2) + noise(yy, 0.007);
plot(xx, yy, blackline{:})

xx = ns(yy, 3.74) + noise(yy, 0.007);
plot(xx, yy, blackline{:})

%# left arrow
x_arr = 1.2:0.1:4.8;
y_arr = 0.65 * ones(size(x_arr)) + noise(x_arr, 0.005);
plot(x_arr, y_arr, blackline{:})
x_head = [1.1 1.6 1.62];
y_head = [0.65 0.72 0.57];
patch(x_head, y_head, 'k')

%# right arrow
x_arr = 8.7:0.1:9.8;
y_arr = 0.65 * ones(size(x_arr)) + noise(x_arr, 0.005);
plot(x_arr, y_arr, blackline{:})
x_head = [9.8 9.3 9.3];
y_head = [0.65 0.72 0.57];
patch(x_head, y_head, 'k')

%# left line on axis
y_line = 0.8:0.1:1.1;
x_line = ns(y_line, 6.5) + noise(y_line, 0.005);
plot(x_line, y_line, blackline{:})

%# right line on axis
y_line = 0.8:0.1:1.1;
x_line = ns(y_line, 7.2) + noise(y_line, 0.005);
plot(x_line, y_line, blackline{:})

%# axes
x_xax = x;
y_xax = 0.95 + noise(x_xax, 0.01);
y_yax = 0.95:0.1:5;
x_yax = x(1) + noise(y_yax, 0.01);
plot(x_xax, y_xax, axisline{:})
plot(x_yax, y_yax, axisline{:})


% finalize 
%# ------------------------

xlim([0.95 10])
ylim([0 5])
axis off

Résultat:

Choses à faire:

  1. Trouver de meilleures fonctions (mieux les définir par morceaux)
  2. Ajouter "annotations" et des lignes ondulées aux courbes qu'ils décrivent
  3. Trouver une meilleure police que Comic Sans!
  4. Généraliser tout dans une fonction plot2xkcd afin que nous puissions convertir n'importe quel intrigue / figure dans le style xkcd.



Related



Tags

matlab   plot