gráficos de estilo xkcd no MATLAB

224

gráfico no estilo xkcd

Pessoas tão talentosas não descobri como fazer xkcd gráficos estilo em Mathematica , em LaTeX , em Python e em R já.

Como alguém pode usar o MATLAB para produzir um gráfico parecido com o descrito acima?

O que eu tentei

Criei linhas onduladas, mas não consegui eixos magros. A única solução que pensei foi substituí-los por linhas onduladas, mas quero poder mudar os eixos reais. Também não consegui que a fonte Humor funcionasse, o bit de código usado era:

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

Para a linha ondulada, experimentei adicionar um pequeno ruído aleatório e suavizar:

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

Mas eu não conseguia fazer o fundo branco aparecer ao redor deles quando eles se cruzam ...

bla
fonte
9
Edit parece satisfazer "fiz algumas pesquisas básicas primeiro". Além disso, as respostas aqui são legais. Reabertura.
Shog9

Respostas:

117

Vejo duas maneiras de resolver isso: A primeira maneira é adicionar um jitter às coordenadas x / y dos recursos da plotagem. Isso tem a vantagem de que você pode modificar facilmente um gráfico, mas precisa desenhar os eixos se quiser txkcdyfied (consulte a solução do @Rody Oldenhuis ). A segunda maneira é criar um gráfico não instável e usar imtransformpara aplicar uma distorção aleatória na imagem. Isso tem a vantagem de poder ser usado com qualquer plotagem, mas você terá uma imagem, não uma plotagem editável.

Vou mostrar o número 2 primeiro e minha tentativa de número 1 abaixo (se você preferir o número 1, veja a solução de Rody !).

insira a descrição da imagem aqui

Esta solução conta com duas funções principais: EXPORT_FIG da troca de arquivos para obter uma captura de tela sem serrilhado e IMTRANSFORM para obter uma transformação.

%# define plot data
x = 1:0.1:10;
y1 = sin(x).*exp(-x/3) + 3;
y2 = 3*exp(-(x-7).^2/2) + 1;

%# plot
fh = figure('color','w');
hold on
plot(x,y1,'b','lineWidth',3);
plot(x,y2,'w','lineWidth',7);
plot(x,y2,'r','lineWidth',3);

xlim([0.95 10])
ylim([0 5])
set(gca,'fontName','Comic Sans MS','fontSize',18,'lineWidth',3,'box','off')

%# add an annotation 
 annotation(fh,'textarrow',[0.4 0.55],[0.8 0.65],...
     'string',sprintf('text%shere',char(10)),'headStyle','none','lineWidth',1.5,...
     'fontName','Comic Sans MS','fontSize',14,'verticalAlignment','middle','horizontalAlignment','left')

%# capture with export_fig
im = export_fig('-nocrop',fh);

%# add a bit of border to avoid black edges
im = padarray(im,[15 15 0],255);

%# make distortion grid
sfc = size(im);
[yy,xx]=ndgrid(1:7:sfc(1),1:7:sfc(2));
pts = [xx(:),yy(:)];
tf = cp2tform(pts+randn(size(pts)),pts,'lwm',12);
w = warning;
warning off images:inv_lwm:cannotEvaluateTransfAtSomeOutputLocations
imt = imtransform(im,tf);
warning(w)

%# remove padding
imt = imt(16:end-15,16:end-15,:);

figure('color','w')
imshow(imt)

Aqui está minha tentativa inicial de tremer

insira a descrição da imagem aqui

%# define plot data
x = 1:0.1:10;
y1 = sin(x).*exp(-x/3) + 3;
y2 = 3*exp(-(x-7).^2/2) + 1;

%# jitter
x = x+randn(size(x))*0.01;
y1 = y1+randn(size(x))*0.01;
y2 = y2+randn(size(x))*0.01;

%# plot
figure('color','w')
hold on
plot(x,y1,'b','lineWidth',3);
plot(x,y2,'w','lineWidth',7);
plot(x,y2,'r','lineWidth',3);

xlim([0.95 10])
ylim([0 5])
set(gca,'fontName','Comic Sans MS','fontSize',18,'lineWidth',3,'box','off')
Jonas
fonte
4
Aproveite o seu tempo no SO enquanto pode! ;)
gnovice
2
@gnovice: Será o meu terceiro. Espero tê-lo praticamente figurado por agora :)
Jonas
@Jonas good job! Acho que o seu # 2 teve a sensação certa para as manobras, entre todas as soluções até agora. No entanto, ainda falta o grande wiggly carrapatos, uma moldura em torno do texto, e desenhado à mão linhas curvas ao ponto do texto para uma linha ...
bla
2
+1 para EXPORT_FIG. Tornando todos os meus gráficos mais agradáveis ​​graças ao anti-aliasing.
21926 Yamaneko
1
@ Jason: desculpe, era o mais próximo que eu tinha disponível na época.
Jonas
92

Em vez de reimplementar todas as várias funções de plotagem, eu queria criar uma ferramenta genérica que pudesse converter qualquer plotagem existente em uma plotagem no estilo xkcd.

Essa abordagem significa que você pode criar plotagens e estilizá-las usando as funções padrão do MATLAB e, quando terminar, poderá renderizar novamente a plotagem no estilo xkcd, preservando o estilo geral da plotagem.

Exemplos

Enredo Digite a descrição da imagem aqui

Bar & Plot

Digite a descrição da imagem aqui

Box & Plot Digite a descrição da imagem aqui

Como funciona

A função funciona iterando sobre os filhos de um eixo. Se as crianças são do tipo lineou as patchdistorcem levemente. Se o filho for do tipo, hggroupele itera nos sub filhos do hggroup. Tenho planos de oferecer suporte a outros tipos de plotagem, comoimage , mas não está claro qual é a melhor maneira de distorcer a imagem para ter um estilo xkcd.

Finalmente, para garantir que as distorções pareçam uniformes (ou seja, as linhas curtas não são distorcidas mais que as longas), eu medo o comprimento da linha em pixels e depois faço uma amostra proporcional ao seu comprimento. Adiciono ruído a cada enésima amostra que produz linhas que apresentam mais ou menos a mesma quantidade de distorção.

O código

Em vez de colar várias centenas de linhas de código, irei apenas vincular a uma essência da fonte . Além disso, o código fonte e o código para gerar os exemplos acima estão disponíveis gratuitamente no GitHub .

Como você pode ver nos exemplos, ele ainda não distorce os eixos, embora eu planeje implementar assim que descobrir a melhor maneira de fazer isso.

Slayton
fonte
4
Agradável! Eu tenho trabalhado um pedaço de código semelhante que implementa a export_figrota, ou seja, ele primeiro formata o gráfico como xkcd e depois distorce a imagem.
Jonas
4
Obrigado. Estou realmente orgulhoso dos gráficos das caixas. Fiquei surpreso com o nível de hacking necessário para que esses planos aparecessem.
slayton
Vou usá-lo para converter minha apresentação inteira em um estilo XKCD.
precisa
Oi Slayton, esses são fantásticos! Eu tenho apenas uma pergunta, existe uma maneira de também fazer os eixos cartoony / xkcd-ish? Isso faria isso por mim e eu seria capaz de usá-lo! :-) Muito obrigado ...
Spacey
@Learnaholic AFAIK Matlab não fornece qualquer api (documentada ou não documentada) para mudar a maneira que os eixos são prestados
slayton
63

O primeiro passo ... encontre uma fonte do sistema que você gosta (use a função listfontspara ver o que está disponível) ou instale uma que corresponda ao estilo de escrita à mão do xkcd . Encontrei uma fonte TrueType "Humor Sans" do usuário ch00f mencionada nesta postagem do blog e a utilizarei nos meus exemplos subseqüentes.

A meu ver, geralmente você precisará de três objetos gráficos modificados diferentes para criar esse tipo de gráfico: um objeto de eixos , um objeto de linha e um objeto de texto . Você também pode querer que um objeto de anotação facilite as coisas, mas prevejo isso por enquanto, pois pode ser mais difícil de implementar do que os três objetos acima.

Criei funções de wrapper que criaram os três objetos, substituindo determinadas configurações de propriedade para torná-las mais parecidas com xkcd. Uma limitação é que os novos gráficos que eles produzem não serão atualizados em certos casos (como caixas delimitadoras em objetos de texto ao redimensionar os eixos), mas isso pode ser explicado por uma implementação orientada a objetos mais completa que envolve a herança do identificador classe , usando eventos e ouvintes , etc. Por enquanto, aqui estão minhas implementações mais simples:

xkcd_axes.m:

function hAxes = xkcd_axes(xkcdOptions, varargin)

  hAxes = axes(varargin{:}, 'NextPlot', 'add', 'Visible', 'off', ...
               'XLimMode', 'manual', 'YLimMode', 'manual');

  axesUnits = get(hAxes, 'Units');
  set(hAxes, 'Units', 'pixels');
  axesPos = get(hAxes, 'Position');
  set(hAxes, 'Units', axesUnits);
  xPoints = round(axesPos(3)/10);
  yPoints = round(axesPos(4)/10);
  limits = [xlim(hAxes) ylim(hAxes)];
  ranges = [abs(limits(2) - limits(1)) abs(limits(4) - limits(3))];
  backColor = get(get(hAxes, 'Parent'), 'Color');
  xColor = get(hAxes, 'XColor');
  yColor = get(hAxes, 'YColor');
  line('Parent', hAxes, 'Color', xColor, 'LineWidth', 3, ...
       'Clipping', 'off', ...
       'XData', linspace(limits(1), limits(2), xPoints), ...
       'YData', limits(3) + rand(1, xPoints).*0.005.*ranges(2));
  line('Parent', hAxes, 'Color', yColor, 'LineWidth', 3, ...
       'Clipping', 'off', ...
       'YData', linspace(limits(3), limits(4), yPoints), ...
       'XData', limits(1) + rand(1, yPoints).*0.005.*ranges(1));

  xTicks = get(hAxes, 'XTick');
  if ~isempty(xTicks)
    yOffset = limits(3) - 0.05.*ranges(2);
    tickIndex = true(size(xTicks));
    if ismember('left', xkcdOptions)
      tickIndex(1) = false;
      xkcd_arrow('left', [limits(1) + 0.02.*ranges(1) xTicks(1)], ...
                 yOffset, xColor);
    end
    if ismember('right', xkcdOptions)
      tickIndex(end) = false;
      xkcd_arrow('right', [xTicks(end) limits(2) - 0.02.*ranges(1)], ...
                 yOffset, xColor);
    end
    plot([1; 1]*xTicks(tickIndex), ...
         0.5.*[-yOffset; yOffset]*ones(1, sum(tickIndex)), ...
         'Parent', hAxes, 'Color', xColor, 'LineWidth', 3, ...
         'Clipping', 'off');
    xLabels = cellstr(get(hAxes, 'XTickLabel'));
    for iLabel = 1:numel(xLabels)
      xkcd_text(xTicks(iLabel), yOffset, xLabels{iLabel}, ...
                'HorizontalAlignment', 'center', ...
                'VerticalAlignment', 'middle', ...
                'BackgroundColor', backColor);
    end
  end

  yTicks = get(hAxes, 'YTick');
  if ~isempty(yTicks)
    xOffset = limits(1) - 0.05.*ranges(1);
    tickIndex = true(size(yTicks));
    if ismember('down', xkcdOptions)
      tickIndex(1) = false;
      xkcd_arrow('down', xOffset, ...
                 [limits(3) + 0.02.*ranges(2) yTicks(1)], yColor);
    end
    if ismember('up', xkcdOptions)
      tickIndex(end) = false;
      xkcd_arrow('up', xOffset, ...
                 [yTicks(end) limits(4) - 0.02.*ranges(2)], yColor);
    end
    plot(0.5.*[-xOffset; xOffset]*ones(1, sum(tickIndex)), ...
         [1; 1]*yTicks(tickIndex), ...
         'Parent', hAxes, 'Color', yColor, 'LineWidth', 3, ...
         'Clipping', 'off');
    yLabels = cellstr(get(hAxes, 'YTickLabel'));
    for iLabel = 1:numel(yLabels)
      xkcd_text(xOffset, yTicks(iLabel), yLabels{iLabel}, ...
                'HorizontalAlignment', 'right', ...
                'VerticalAlignment', 'middle', ...
                'BackgroundColor', backColor);
    end
  end

  function xkcd_arrow(arrowType, xArrow, yArrow, arrowColor)
    if ismember(arrowType, {'left', 'right'})
      xLine = linspace(xArrow(1), xArrow(2), 10);
      yLine = yArrow + rand(1, 10).*0.003.*ranges(2);
      arrowScale = 0.05.*ranges(1);
      if strcmp(arrowType, 'left')
        xArrow = xLine(1) + arrowScale.*[0 0.5 1 1 1 0.5];
        yArrow = yLine(1) + arrowScale.*[0 0.125 0.25 0 -0.25 -0.125];
      else
        xArrow = xLine(end) - arrowScale.*[0 0.5 1 1 1 0.5];
        yArrow = yLine(end) + arrowScale.*[0 -0.125 -0.25 0 0.25 0.125];
      end
    else
      xLine = xArrow + rand(1, 10).*0.003.*ranges(1);
      yLine = linspace(yArrow(1), yArrow(2), 10);
      arrowScale = 0.05.*ranges(2);
      if strcmp(arrowType, 'down')
        xArrow = xLine(1) + arrowScale.*[0 0.125 0.25 0 -0.25 -0.125];
        yArrow = yLine(1) + arrowScale.*[0 0.5 1 1 1 0.5];
      else
        xArrow = xLine(end) + arrowScale.*[0 -0.125 -0.25 0 0.25 0.125];
        yArrow = yLine(end) - arrowScale.*[0 0.5 1 1 1 0.5];
      end
    end
    line('Parent', hAxes, 'Color', arrowColor, 'LineWidth', 3, ...
         'Clipping', 'off', 'XData', xLine, 'YData', yLine);
    patch('Parent', hAxes, 'FaceColor', arrowColor, ...
          'EdgeColor', arrowColor, 'LineWidth', 2, 'Clipping', 'off', ...
          'XData', xArrow + [0 rand(1, 5).*0.002.*ranges(1)], ...
          'YData', yArrow + [0 rand(1, 5).*0.002.*ranges(2)]);
  end

end

xkcd_text.m:

function hText = xkcd_text(varargin)

  hText = text(varargin{:});
  set(hText, 'FontName', 'Humor Sans', 'FontSize', 13, ...
      'FontWeight', 'normal');

  backColor = get(hText, 'BackgroundColor');
  edgeColor = get(hText, 'EdgeColor');
  if ~strcmp(backColor, 'none') || ~strcmp(edgeColor, 'none')
    hParent = get(hText, 'Parent');
    extent = get(hText, 'Extent');
    nLines = size(get(hText, 'String'), 1);
    extent = extent + [-0.5 -0.5 1 1].*0.25.*extent(4)./nLines;
    yPoints = 5*nLines;
    xPoints = round(yPoints*extent(3)/extent(4));
    noiseScale = 0.05*extent(4)/nLines;
    set(hText, 'BackgroundColor', 'none', 'EdgeColor', 'none');
    xBox = [linspace(extent(1), extent(1) + extent(3), xPoints) ...
            extent(1) + extent(3) + noiseScale.*rand(1, yPoints) ...
            linspace(extent(1) + extent(3), extent(1), xPoints) ...
            extent(1) + noiseScale.*rand(1, yPoints)];
    yBox = [extent(2) + noiseScale.*rand(1, xPoints) ...
            linspace(extent(2), extent(2) + extent(4), yPoints) ...
            extent(2) + extent(4) + noiseScale.*rand(1, xPoints) ...
            linspace(extent(2) + extent(4), extent(2), yPoints)];
    patch('Parent', hParent, 'FaceColor', backColor, ...
          'EdgeColor', edgeColor, 'LineWidth', 2, 'Clipping', 'off', ...
          'XData', xBox, 'YData', yBox);
    hKids = get(hParent, 'Children');
    set(hParent, 'Children', [hText; hKids(hKids ~= hText)]);
  end

end

xkcd_line.m:

function hLine = xkcd_line(xData, yData, varargin)

  yData = yData + 0.01.*max(range(xData), range(yData)).*rand(size(yData));
  line(xData, yData, varargin{:}, 'Color', 'w', 'LineWidth', 8);
  hLine = line(xData, yData, varargin{:}, 'LineWidth', 3);

end

E aqui está um exemplo de script que os utiliza para recriar os quadrinhos acima. Recriei as linhas usando ginputpara marcar pontos no gráfico com o mouse, capturando-os e plotando-os como eu queria:

xS = [0.0359 0.0709 0.1004 0.1225 0.1501 0.1759 0.2219 0.2477 0.2974 0.3269 0.3582 0.3895 0.4061 0.4337 0.4558 0.4797 0.5074 0.5276 0.5589 0.5810 0.6013 0.6179 0.6271 0.6344 0.6381 0.6418 0.6529 0.6713 0.6842 0.6934 0.7026 0.7118 0.7265 0.7376 0.7560 0.7726 0.7836 0.7965 0.8149 0.8370 0.8573 0.8867 0.9033 0.9346 0.9659 0.9843 0.9936];
yS = [0.2493 0.2520 0.2548 0.2548 0.2602 0.2629 0.2629 0.2657 0.2793 0.2657 0.2575 0.2575 0.2602 0.2629 0.2657 0.2766 0.2793 0.2875 0.3202 0.3856 0.4619 0.5490 0.6771 0.7670 0.7970 0.8270 0.8433 0.8433 0.8243 0.7180 0.6199 0.5272 0.4510 0.4128 0.3392 0.2711 0.2275 0.1757 0.1485 0.1131 0.1022 0.0858 0.0858 0.1022 0.1267 0.1567 0.1594];

xF = [0.0304 0.0488 0.0727 0.0967 0.1335 0.1630 0.2090 0.2348 0.2698 0.3011 0.3269 0.3545 0.3803 0.4153 0.4466 0.4724 0.4945 0.5110 0.5350 0.5516 0.5608 0.5700 0.5755 0.5810 0.5884 0.6013 0.6179 0.6363 0.6492 0.6584 0.6676 0.6731 0.6842 0.6860 0.6934 0.7007 0.7136 0.7265 0.7394 0.7560 0.7726 0.7818 0.8057 0.8444 0.8794 0.9107 0.9475 0.9751 0.9917];
yF = [0.0804 0.0940 0.0967 0.1049 0.1185 0.1458 0.1512 0.1540 0.1649 0.1812 0.1812 0.1703 0.1621 0.1594 0.1703 0.1975 0.2411 0.3065 0.3801 0.4782 0.5708 0.6526 0.7452 0.8106 0.8324 0.8488 0.8433 0.8270 0.7888 0.7343 0.6826 0.5981 0.5300 0.4782 0.3910 0.3420 0.2847 0.2248 0.1621 0.0995 0.0668 0.0395 0.0232 0.0177 0.0204 0.0232 0.0259 0.0204 0.0232];

xE = [0.0267 0.0488 0.0856 0.1409 0.1759 0.2164 0.2514 0.3011 0.3269 0.3637 0.3969 0.4245 0.4503 0.4890 0.5313 0.5608 0.5939 0.6344 0.6694 0.6934 0.7192 0.7394 0.7523 0.7689 0.7891 0.8131 0.8481 0.8757 0.9070 0.9346 0.9604 0.9807 0.9936];
yE = [0.0232 0.0232 0.0232 0.0259 0.0259 0.0259 0.0313 0.0259 0.0259 0.0259 0.0368 0.0395 0.0477 0.0586 0.0777 0.0886 0.1213 0.1730 0.2466 0.2902 0.3638 0.5082 0.6499 0.7916 0.8924 0.9414 0.9550 0.9387 0.9060 0.8760 0.8542 0.8379 0.8188];

hFigure = figure('Position', [300 300 700 450], 'Color', 'w');
hAxes = xkcd_axes({'left', 'right'}, 'XTick', [0.45 0.60 0.7 0.8], ...
                  'XTickLabel', {'YARD', 'STEPS', 'DOOR', 'INSIDE'}, ...
                  'YTick', []);

hSpeed = xkcd_line(xS, yS, 'Parent', hAxes, 'Color', [0.5 0.5 0.5]);
hFear = xkcd_line(xF, yF, 'Parent', hAxes, 'Color', [0 0.5 1]);
hEmb = xkcd_line(xE, yE, 'Parent', hAxes, 'Color', 'r');

hText = xkcd_text(0.27, 0.9, ...
                  {'WALKING BACK TO MY'; 'FRONT DOOR AT NIGHT:'}, ...
                  'Parent', hAxes, 'EdgeColor', 'k', ...
                  'HorizontalAlignment', 'center');

hSpeedNote = xkcd_text(0.36, 0.35, {'FORWARD'; 'SPEED'}, ...
                       'Parent', hAxes, 'Color', 'k', ...
                       'HorizontalAlignment', 'center');
hSpeedLine = xkcd_line([0.4116 0.4282 0.4355 0.4411], ...
                       [0.3392 0.3256 0.3038 0.2820], ...
                       'Parent', hAxes, 'Color', 'k');
hFearNote = xkcd_text(0.15, 0.45, {'FEAR'; 'THAT THERE''S'; ...
                                   'SOMETHING'; 'BEIND ME'}, ...
                      'Parent', hAxes, 'Color', 'k', ...
                      'HorizontalAlignment', 'center');
hFearLine = xkcd_line([0.1906 0.1998 0.2127 0.2127 0.2201 0.2256], ...
                      [0.3501 0.3093 0.2629 0.2221 0.1975 0.1676], ...
                      'Parent', hAxes, 'Color', 'k');
hEmbNote = xkcd_text(0.88, 0.45, {'EMBARRASSMENT'}, ...
                     'Parent', hAxes, 'Color', 'k', ...
                     'HorizontalAlignment', 'center');
hEmbLine = xkcd_line([0.8168 0.8094 0.7983 0.7781 0.7578], ...
                     [0.4864 0.5436 0.5872 0.6063 0.6226], ...
                     'Parent', hAxes, 'Color', 'k');

E (trombetas) aqui está o gráfico resultante !:

insira a descrição da imagem aqui

gnovice
fonte
2
Maravilhoso! meu único comentário é que as linhas que apontam para o texto devem ser mais finas e curvas (menos onduladas).
bla
4
Isso é fantástico, embora a trama sofra aliases. Eu escrevi um breve post sobre como lidar com essa aqui: hugocarr.com/index/xkcd-style-graphs-in-matlab
Huguenot
28

OK, então, aqui está a minha tentativa menos grosseira, mas ainda não muito clara:

%# 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

Resultado:

Imitação de XKCD no Matlab

Coisas para fazer:

  1. Encontre funções melhores (defina-as melhor por partes)
  2. Adicione "anotações" e linhas onduladas às curvas que descrevem
  3. Encontre uma fonte melhor do que Comic Sans!
  4. Generalize tudo em uma função plot2xkcdpara que possamos converter qualquer plot / figura no estilo xkcd.
Rody Oldenhuis
fonte
1
Bom trabalho com cores e machados! Eu sinto que eles são um pouco nervosos, no entanto. +1 de qualquer maneira.
Jonas3
@HighPerormanceMark: Eu ainda não acho que tudo isso é muito útil, no entanto, é muito divertido :)
Rody Oldenhuis
@RodyOldenhuis porque não é útil? Acho as plotagens estilizadas mais bonitas do que as plotagens originais. Adicionar estilo é certamente uma função válida.
slayton
2
@slayton: Vamos usar uma ferramenta de processamento de números muito avançada, projetada para ser supereficiente, capaz de criar belos gráficos prontos para publicação da maneira mais precisa possível, e vamos usá-la para criar ... ** quadrinhos ** com ele . Desculpe, isso é bobo. No entanto, é muito divertido , e é por isso que a maioria das pessoas votou aqui e o que fez a pergunta reabrir. Isso será útil para futuros visitantes? Bem ... se inspirar. Talvez isso convide algumas pessoas a aprender Matlab. Mas fazer o trabalho de estilo xkcd adequadamente exigirá cortes e técnicas que são uhm ... questionável, pelo menos :)
Rody Oldenhuis
6
@RodyOldenhuis: Eu, por exemplo, usarei esses gráficos em minhas apresentações. E geralmente é com os "hacks" que você realmente aprende como o ambiente funciona.
Jonas