Графіки стилів xkcd у MATLAB


224

Графік стилю xkcd

Так талановиті люди з'ясували , як зробити XKCD графіки стилю в Mathematica , в латексі , в Python і в R вже.

Як можна використовувати MATLAB для створення ділянки, схожого на описаний вище?

Що я спробував

Я створив вігглі лінії, але я не міг отримати віггі осей. Єдине рішення, про яке я думав, - це перезаписати їх химерними лініями, але я хочу мати змогу змінити фактичні осі. Я також не міг змусити шрифт Humor працювати, використовуваний біт коду:

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

Для лінії wiggly я експериментував з додаванням невеликого випадкового шуму і згладжування:

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

Але я не міг зробити, щоб білий фон з'явився навколо них, коли вони перетинаються ...


9
Здається, редагування задовольняє "спочатку провели деякі основні дослідження". Також відповіді тут приємні. Повторне відкриття.
Shog9

Відповіді:


117

Я бачу два шляхи вирішення цього питання: Перший спосіб - додати трохи джиттера до координат x / y функцій сюжету. Це має перевагу в тому, що ви можете легко змінювати сюжет, але вам потрібно намалювати осі самостійно, якщо ви хочете, щоб вони були xkcdyfied (див. Рішення @ Роді Олденхуйса ). Другий спосіб - створити сюжетний сюжет і застосувати imtransformдо зображення випадкове спотворення. Це має перевагу в тому, що ви можете використовувати його з будь-яким сюжетом, але ви отримаєте зображення, а не сюжет, який можна редагувати.

Спочатку я покажу №2, і моя спроба в №1 нижче (якщо вам більше подобається №1, подивіться на рішення Роді !).

введіть тут опис зображення

Це рішення покладається на дві ключові функції: EXPORT_FIG з файлового обміну, щоб отримати скріншот анти-псевдоніму, і IMTRANSFORM для отримання перетворення.

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

Ось моя перша спроба тремтіння

введіть тут опис зображення

%# 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
Насолоджуйтесь своїм часом на ТАК, поки зможете! ;)
gnovice

2
@gnovice: Це буде мій третій. Я сподіваюся, що це я вже зараз зрозумів :)
Jonas

@Jonas хороша робота! Я думаю, що ваш номер 2 отримав справжнє відчуття ворушіння, серед усіх рішень досі. Однак, він все ще не вистачає великих хитких кліщів, рамки навколо тексту та витягнутих руками вигнутих ліній для вказівки від тексту до рядка ...
bla

2
+1 для EXPORT_FIG. Перетворення всіх моїх графіків більш приємним завдяки анти-згладжуванню.
Яманеко

1
@JasonS: Вибачте, це було найближче у мене на той час доступ.
Йонас

92

Замість того, щоб повторно реалізовувати всі різні функції побудови графіку, я хотів створити загальний інструмент, який міг би перетворити будь-який існуючий сюжет у графічний стиль xkcd.

Такий підхід означає, що ви можете створювати сюжети та стилювати їх за допомогою стандартних функцій MATLAB, а потім, коли ви закінчите, зможете повторно відтворити сюжет у стилі xkcd, зберігаючи загальний стиль сюжету.

Приклади

Сюжет Введіть тут опис зображення

Бар & Сюжет

Введіть тут опис зображення

Коробка та ділянка Введіть тут опис зображення

Як це працює

Функція працює за допомогою ітерації над дітьми осей. Якщо діти типу, lineабо patchце їх дещо спотворює. Якщо дитина hggroupнабирає тип, то вона повторюється на піддітях hggroup. У мене є плани підтримувати інші типи сюжетів, такі як image, але незрозуміло, який найкращий спосіб спотворити зображення, щоб мати стиль xkcd.

Нарешті, щоб перекоси виглядали рівномірними (тобто короткі лінії не дистрогувались більше, ніж довгі рядки), я вимірюю довжину лінії в пікселях, а потім збільшую вибірку пропорційно її довжині. Потім я додаю шум до кожного N-го зразка, який видає лінії, які мають більш-менш однакову кількість спотворень.

Код

Замість того, щоб вставляти кілька сотень рядків коду, я просто посилаюсь на суть джерела . Додатково вихідний код та код для створення наведених вище прикладів є у вільному доступі GitHub .

Як видно з прикладів, він ще не спотворює самі осі, хоча я планую здійснити, як тільки я зрозумію найкращий спосіб зробити це.


4
Приємно! Я працював подібний фрагмент коду, який реалізує export_figмаршрут, тобто він спочатку формує графік, подібний xkcd, а потім спотворює зображення.
Йонас

4
Дякую. Я справді пишаюся коробками сюжетів. Я був здивований рівнем злому, необхідного для показу цих сюжетів.
слайтон

Я буду використовувати його для перетворення всієї презентації у стиль XKCD.
Яманеко

Привіт Слайтоне, це фантастично! У мене є лише одне запитання, чи є також спосіб зробити осі мультфільмами / xkcd-ish? Це зробило б це для мене, і я зможу ним скористатися! :-) Велике спасибі ...
Spacey

@Learnaholic AFAIK matlab не надає жодних api (задокументованих або недокументованих), щоб змінити спосіб надання осей
slayton

63

Перший крок ... знайдіть вподобаний шрифт системи (скористайтеся функцією, listfontsщоб побачити, що є в наявності) або встановіть той, який відповідає стилю рукописного тексту від xkcd . Я знайшов шрифт TrueType "Humor Sans" від користувача ch00f, згаданий у цій публікації в блозі , і буду використовувати його для моїх наступних прикладів.

Як я бачу, вам, як правило, потрібні три різні модифіковані графічні об’єкти для створення таких типів графіків: об'єкт осей , лінійний об'єкт , і текстовий об'єкт . Можливо, ви також хочете, щоб об’єкт анотації полегшив ситуацію, але я передбачив, що наразі це може бути складніше, ніж вищевказані три об'єкти.

Я створив функції обгортки, які створили три об’єкти, змінивши певні параметри властивості, щоб зробити їх більш схожими на xkcd. Одне обмеження полягає в тому, що нова графіка, яку вони створюють, не буде оновлюватися в певних випадках (наприклад, обмеження полів на текстових об'єктах при зміні розміру осей), але це може бути пояснено більш повною об'єктно-орієнтованою реалізацією, яка передбачає успадкування від ручки клас , використовуючи події та слухачів тощо. Наразі ось мої простіші реалізації:

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

І ось зразок сценарію, який використовує їх для відтворення вищезгаданого коміксу. Я відтворив лінії за допомогоюginput позначення точок на ділянці мишею, захопивши їх, а потім побудував їх, як я хотів:

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');

І (труби) ось отриманий сюжет !:

введіть тут опис зображення


2
Чудово! мій єдиний коментар - це те, що лінії, які вказують на текст, повинні бути тоншими та вигнутими (менш химерними).
бла

4
Це фантастично, хоча сюжет страждає від згладжування. Я написав короткий пост про те, як боротися з цим тут: hugocarr.com/index/xkcd-style-graphs-in-matlab
Huguenot

28

Добре тоді, ось моя менш жорстка спроба, але все-таки не дуже-є ще спроба:

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

Результат:

Імітація XKCD в Matlab

Що робити:

  1. Знайдіть кращі функції (краще визначте їх детально)
  2. Додайте «анотації» та хвилясті лінії до кривих, які вони описують
  3. Знайдіть кращий шрифт, ніж Comic Sans!
  4. Узагальнити все у функції, plot2xkcdщоб ми могли перетворити будь-який сюжет / фігуру у стиль xkcd.

1
Гарна робота з квітами та сокирами! Я відчуваю, що вони трохи надто хвилюючі. +1 у будь-якому випадку
Йонас

@HighPerormanceMark: Я все ще не думаю, що це все дуже корисно, однак, це дуже цікаво :)
Rody Oldenhuis

@RodyOldenhuis чому не корисно? Я вважаю, що стильові сюжети виглядають краще, ніж оригінальні сюжети. Додавання стилю, безумовно, є дійсною функцією.
слайтон

2
@slayton: Візьмемо один дуже просунутий інструмент для стискання чисел, який був розроблений як надзвичайно ефективний, здатний максимально точно зробити красиві сюжети, готові до публікації, і давайте використовувати його для створення ... ** коміксів ** із ним . Вибачте, це просто нерозумно. Однак це приємно весело , саме тому більшість людей тут схвалили голову і чому питання було відкрито. Чи корисно це буде майбутнім відвідувачам? Ну ... це дійсно надихає. Можливо, це запросить деяких людей вивчити Matlab. Але для правильної роботи в стилі xkcd потрібні хаки та прийоми, які є уж ... принаймні
сумнівними

6
@RodyOldenhuis: Я, наприклад, буду використовувати ці графіки у своїх презентаціях. І зазвичай з "хаками" ви дійсно дізнаєтесь, як працює середовище.
Йонас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.