grafici in stile xkcd in MATLAB


225

grafico in stile xkcd

Persone così di talento hanno capito come rendere xkcd grafici stile di Mathematica , in LaTeX , in Python e in R già.

Come si può usare MATLAB per produrre una trama simile a quella sopra?

Quello che ho provato

Ho creato linee ondulate, ma non sono riuscito a ottenere assi irregolari. L'unica soluzione a cui ho pensato è stata di sovrascriverli con linee ondulate, ma voglio essere in grado di cambiare gli assi reali. Inoltre non sono riuscito a far funzionare il font Humor, il bit di codice utilizzato era:

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

Per la linea ondulata, ho sperimentato l'aggiunta di un piccolo rumore casuale e il livellamento:

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

Ma non riuscivo a far apparire lo sfondo bianco attorno a loro quando si intersecano ...


9
La modifica sembra soddisfare "prima alcune ricerche di base". Inoltre, le risposte qui sono buone. Riapertura.
Shog9

Risposte:


118

Vedo due modi per risolverlo: il primo è aggiungere jitter alle coordinate x / y delle caratteristiche del grafico. Questo ha il vantaggio di poter modificare facilmente una trama, ma devi disegnare tu stesso gli assi se vuoi averli xkcdyfied (vedi la soluzione di @Rody Oldenhuis ). Il secondo modo è quello di creare un grafico non nervoso e utilizzare imtransformper applicare una distorsione casuale all'immagine. Questo ha il vantaggio che puoi usarlo con qualsiasi trama, ma finirai con un'immagine, non con una trama modificabile.

Mostrerò prima il n. 2 e il mio tentativo al n. 1 in basso (se ti piace il n. 1 meglio, guarda la soluzione di Rody !).

inserisci qui la descrizione dell'immagine

Questa soluzione si basa su due funzioni chiave: EXPORT_FIG dallo scambio di file per ottenere uno screenshot con anti-alias e IMTRANSFORM per ottenere una trasformazione.

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

Ecco il mio primo tentativo di jittering

inserisci qui la descrizione dell'immagine

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

4
Goditi il ​​tuo tempo su SO mentre puoi! ;)
gnovice,

2
@gnovice: sarà il mio terzo. Spero di averlo praticamente capito ormai :)
Jonas,

@Jonas buon lavoro! Penso che il tuo numero 2 abbia avuto la giusta sensazione per le oscillazioni, tra tutte le soluzioni finora. Tuttavia, manca ancora i grandi segni di spunta, una cornice attorno al testo e linee curve disegnate a mano per puntare dal testo a una linea ...
Bla

2
+1 per EXPORT_FIG. Rendendo tutti i miei grafici più gradevoli grazie all'antialiasing.
Yamaneko,

1
@JasonS: scusa, era il più vicino che avevo disponibile al momento.
Jonas,

92

Invece di reimplementare tutte le varie funzioni di stampa, volevo creare uno strumento generico in grado di convertire qualsiasi trama esistente in una trama in stile xkcd.

Questo approccio significa che è possibile creare grafici e modellarli utilizzando le funzioni MATLAB standard e, al termine, è possibile ripetere il rendering del grafico in uno stile xkcd preservando lo stile generale del grafico.

Esempi

Tracciare Inserisci qui la descrizione dell'immagine

Bar e trama

Inserisci qui la descrizione dell'immagine

Scatola e trama Inserisci qui la descrizione dell'immagine

Come funziona

La funzione funziona ripetendo i figli degli assi. Se i bambini sono di tipo lineo patchli distorce leggermente. Se il figlio è di tipo hggroup, scorre i sotto-figli del file hggroup. Ho in programma di supportare altri tipi di trama, come image, ma non è chiaro quale sia il modo migliore per distorcere l'immagine per avere uno stile xkcd.

Infine, per garantire che le distorsioni appaiano uniformi (ovvero, le linee corte non sono distorte più delle linee lunghe), misuro la lunghezza della linea in pixel e quindi il campione è proporzionale alla sua lunghezza. Aggiungo quindi rumore a ogni ennesimo campione che produce linee che hanno più o meno la stessa quantità di distorsione.

Il codice

Piuttosto che incollare diverse centinaia di righe di codice, collegherò solo a una sintesi della fonte . Inoltre, il codice sorgente e il codice per generare gli esempi sopra sono GitHub liberamente disponibili .

Come puoi vedere dagli esempi, non distorce ancora gli assi stessi, anche se ho intenzione di implementare non appena trovo il modo migliore per farlo.


4
Bello! Ho lavorato su un codice simile che implementa il export_figpercorso, ovvero formatta prima la trama in stile xkcd e quindi distorce l'immagine.
Jonas,

4
Grazie. Sono davvero orgoglioso dei grafici a scatole. Sono rimasto sorpreso dal livello di hacking richiesto per far sì che quei grafici venissero mostrati.
slayton,

Lo userò per convertire la mia intera presentazione in uno stile XKCD.
Yamaneko,

Ciao Slayton, quelli sono fantastici! Ho solo una domanda, c'è un modo per rendere anche gli assi cartoony / xkcd-ish? Lo farebbe per me e sarei in grado di usarlo! :-) Mille grazie ...
Spacey,

@Learnaholic AFAIK matlab non fornisce alcuna API (documentata o non documentata) per cambiare il modo in cui gli assi sono resi
slayton,

63

Il primo passo ... trova un font di sistema che ti piace (usa la funzione listfontsper vedere cosa è disponibile) o installane uno che corrisponda allo stile di scrittura a mano da xkcd . Ho trovato un carattere TrueType "Humor Sans" dell'utente ch00f menzionato in questo post del blog e lo userò per i miei esempi successivi.

A mio avviso, in genere avrai bisogno di tre diversi oggetti grafici modificati per creare questi tipi di grafici: un oggetto axes , un oggetto linea e un oggetto testo . Potresti anche voler un oggetto di annotazione per rendere le cose più facili, ma per ora lo prevedo perché potrebbe essere più difficile da implementare rispetto ai tre oggetti precedenti.

Ho creato funzioni wrapper che hanno creato i tre oggetti, ignorando alcune impostazioni delle proprietà per renderle più simili a xkcd. Una limitazione è che la nuova grafica che producono non verrà aggiornata in alcuni casi (come i riquadri di delimitazione sugli oggetti di testo durante il ridimensionamento degli assi), ma che potrebbe essere spiegata con un'implementazione orientata agli oggetti più completa che comporta l'ereditarietà dall'handle lezione , utilizzo di eventi e ascoltatori , ecc. Per ora, ecco le mie implementazioni più semplici:

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

Ed ecco uno script di esempio che li utilizza per ricreare il fumetto di cui sopra. Ho ricreato le linee usando ginputper segnare i punti nella trama con il mouse, catturandoli e poi disegnandoli come volevo:

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 (trombe) ecco la trama risultante !:

inserisci qui la descrizione dell'immagine


2
Meraviglioso! il mio unico commento è che le linee che puntano dal testo dovrebbero essere più sottili e più curve (meno ondulate).
Bla

4
Questo è fantastico, anche se la trama soffre di aliasing. Ho scritto un breve post su come gestirlo
Huguenot

28

OK allora, ecco il mio tentativo meno rozzo ma ancora non del tutto lì:

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

Risultato:

Imitazione XKCD in Matlab

Cose da fare:

  1. Trova funzioni migliori (definiscile meglio in base al pezzo)
  2. Aggiungi "annotazioni" e linee ondulate alle curve che descrivono
  3. Trova un carattere migliore di Comic Sans!
  4. Generalizza tutto in una funzione in plot2xkcdmodo da poter convertire qualsiasi trama / figura nello stile xkcd.

1
Bel lavoro con colori e asce! Sento che sono un po 'troppo nervosi, però. +1 comunque.
Jonas,

@HighPerormanceMark: Io ancora non credo che tutto questo è molto utile, tuttavia, è molto divertente :)
Rody Oldenhuis

@RodyOldenhuis perché non utile? Trovo che le trame in stile siano più belle delle trame originali. L'aggiunta di stile è sicuramente una funzione valida.
slayton,

2
@slayton: prendiamo uno strumento di crunching numerico molto avanzato che è stato progettato per essere super efficiente, in grado di realizzare bellissime trame pronte per la pubblicazione nel modo più preciso possibile e usiamolo per creare ... ** fumetti ** con esso . Scusa, è solo sciocco. È comunque molto divertente , motivo per cui la maggior parte delle persone qui votate e ciò che ha riaperto la domanda. Questo sarà di qualche utilità per i futuri visitatori? Beh ... non ispirare. Forse inviterà alcune persone a imparare Matlab. Ma far funzionare correttamente lo stile xkcd richiederà hack e tecniche che sono uhm ... per lo meno discutibili :)
Rody Oldenhuis,

6
@RodyOldenhuis: io, per esempio, userò questi grafici nelle mie presentazioni. Ed è di solito con gli "hack" che impari davvero come funziona l'ambiente.
Jonas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.