đồ thị kiểu xkcd trong MATLAB


224

đồ thị kiểu xkcd

Vì vậy, những người tài năng đã tìm ra cách tạo các biểu đồ kiểu xkcd trong Mathematica , trong LaTeX , trong Pythontrong R rồi.

Làm thế nào người ta có thể sử dụng MATLAB để tạo ra một cốt truyện giống như ở trên?

Những gì tôi đã cố gắng

Tôi đã tạo ra các đường uốn lượn, nhưng tôi không thể có được các trục uốn lượn. Giải pháp duy nhất tôi nghĩ đến là ghi đè lên chúng bằng các đường uốn lượn, nhưng tôi muốn có thể thay đổi các trục thực tế. Tôi cũng không thể làm cho phông chữ Hài hước hoạt động, bit mã được sử dụng là:

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

Đối với dòng uốn lượn, tôi đã thử nghiệm thêm một tiếng ồn nhỏ và làm mịn:

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

Nhưng tôi không thể làm cho nền trắng xuất hiện xung quanh chúng khi chúng giao nhau ...


9
Chỉnh sửa dường như đáp ứng "một số nghiên cứu cơ bản đầu tiên". Ngoài ra, câu trả lời ở đây là tốt đẹp. Mở lại.
Shog9

Câu trả lời:


117

Tôi thấy có hai cách để giải quyết điều này: Cách đầu tiên là thêm một số jitter vào tọa độ x / y của các tính năng cốt truyện. Điều này có lợi thế là bạn có thể dễ dàng sửa đổi cốt truyện, nhưng bạn phải tự vẽ trục nếu bạn muốn có xkcdyfied (xem giải pháp của @Rody Oldenhuis ). Cách thứ hai là tạo ra một cốt truyện không bị giật, và sử dụng imtransformđể áp dụng một biến dạng ngẫu nhiên cho hình ảnh. Điều này có lợi thế là bạn có thể sử dụng nó với bất kỳ cốt truyện nào, nhưng bạn sẽ kết thúc bằng một hình ảnh, không phải là một cốt truyện có thể chỉnh sửa.

Tôi sẽ hiển thị số 2 trước và nỗ lực của tôi ở số 1 bên dưới (nếu bạn thích số 1 hơn, hãy xem giải pháp của Rody !).

nhập mô tả hình ảnh ở đây

Giải pháp này dựa trên hai chức năng chính: Billing_FIG từ trao đổi tệp để có được một ảnh chụp màn hình chống răng cưa và IMTRANSFORM để có được một chuyển đổi.

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

Đây là nỗ lực ban đầu của tôi trong việc hốt hoảng

nhập mô tả hình ảnh ở đây

%# 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
Tận hưởng thời gian của bạn trên SO trong khi bạn có thể! ;)
gnovice

2
@gnovice: Nó sẽ là cái thứ ba của tôi. Tôi hy vọng bây giờ tôi đã tìm ra nó khá nhiều :)
Jonas

@Jonas làm tốt lắm! Tôi nghĩ rằng số 2 của bạn có cảm giác đúng đắn cho những cái lắc lư, trong số tất cả các giải pháp cho đến nay. Tuy nhiên, nó vẫn bỏ lỡ những con bọ chét lớn, một khung bao quanh văn bản và vẽ tay các đường cong để chỉ từ văn bản đến một dòng ...
bla

2
+1 cho XUẤT KHẨU. Biến tất cả các biểu đồ của tôi làm hài lòng hơn nhờ khử răng cưa.
Yamaneko

1
@JasonS: xin lỗi, đó là lần gần nhất tôi có sẵn tại thời điểm đó.
Jonas

92

Thay vì triển khai lại tất cả các hàm vẽ khác nhau, tôi muốn tạo một công cụ chung có thể chuyển đổi bất kỳ âm mưu hiện có nào thành một biểu đồ kiểu xkcd.

Cách tiếp cận này có nghĩa là bạn có thể tạo các ô và định kiểu chúng bằng các hàm MATLAB tiêu chuẩn và sau đó khi bạn hoàn thành, bạn có thể kết xuất lại cốt truyện theo kiểu xkcd trong khi vẫn giữ nguyên phong cách chung của cốt truyện.

Ví dụ

Âm mưu Nhập mô tả hình ảnh ở đây

Bar & lô

Nhập mô tả hình ảnh ở đây

Hộp & lô Nhập mô tả hình ảnh ở đây

Làm thế nào nó hoạt động

Hàm này hoạt động bằng cách lặp qua các con của một trục. Nếu những đứa trẻ thuộc loại linehoặc patchnó làm biến dạng chúng một chút. Nếu đứa trẻ thuộc kiểu hggroupđó thì lặp đi lặp lại trên con con của hggroup. Tôi có kế hoạch hỗ trợ các loại cốt truyện khác, chẳng hạn image, nhưng không rõ cách tốt nhất để làm biến dạng hình ảnh để có kiểu xkcd là gì.

Cuối cùng để đảm bảo rằng các biến dạng trông đồng nhất (nghĩa là các dòng ngắn không bị phân tán nhiều hơn các dòng dài), tôi đo chiều dài dòng tính bằng pixel và sau đó tăng mẫu tỷ lệ với độ dài của nó. Sau đó tôi thêm nhiễu vào mỗi mẫu thứ N tạo ra các dòng có ít nhiều biến dạng như nhau.

Mật mã

Thay vì dán hàng trăm dòng mã, tôi sẽ chỉ liên kết đến một ý chính của nguồn . Ngoài ra, mã nguồn và mã để tạo các ví dụ trên là GitHub có sẵn miễn phí .

Như bạn có thể thấy từ các ví dụ, nó chưa tự làm biến dạng các trục mặc dù tôi có kế hoạch thực hiện ngay khi tôi tìm ra cách tốt nhất để làm điều đó.


4
Đẹp! Tôi đã làm việc với một đoạn mã tương tự thực hiện export_figtuyến đường, tức là trước tiên nó định dạng cốt truyện giống xkcd, và sau đó làm biến dạng hình ảnh.
Jonas

4
Cảm ơn. Tôi thực sự tự hào về các ô hộp. Tôi đã ngạc nhiên ở mức độ hack cần thiết để có được những âm mưu đó để hiển thị.
slayton

Tôi sẽ sử dụng nó để chuyển đổi toàn bộ bài thuyết trình của mình thành kiểu XKCD.
Yamaneko

Xin chào Slayton, đó là những người tuyệt vời! Tôi chỉ có một câu hỏi, có cách nào để làm cho các trục hoạt hình / xkcd-ish không? Điều đó sẽ làm điều đó cho tôi và tôi sẽ có thể sử dụng nó! :-) Rất cám ơn ...
Spacey

@Learnaholic AFAIK matlab không cung cấp bất kỳ api nào (được ghi lại hoặc không có giấy tờ) để thay đổi cách hiển thị các trục
slayton

63

Bước đầu tiên ... tìm một phông chữ hệ thống mà bạn thích (sử dụng chức năng listfontsđể xem những gì có sẵn) hoặc cài đặt một phông chữ phù hợp với kiểu chữ viết tay từ xkcd . Tôi đã tìm thấy phông chữ TrueType "Humor Sans" từ người dùng ch00f được đề cập trong bài đăng trên blog này và sẽ sử dụng nó cho các ví dụ tiếp theo của tôi.

Như tôi thấy, nhìn chung bạn sẽ cần ba đối tượng đồ họa được sửa đổi khác nhau để tạo ra các loại biểu đồ này: một đối tượng trục , đối tượng đườngđối tượng văn bản . Bạn cũng có thể muốn một đối tượng chú thích để làm cho mọi thứ dễ dàng hơn, nhưng tôi đã biết trước điều này vì nó có thể khó thực hiện hơn ba đối tượng trên.

Tôi đã tạo các hàm bao bọc tạo ra ba đối tượng, ghi đè các cài đặt thuộc tính nhất định để làm cho chúng giống xkcd hơn. Một hạn chế là đồ họa mới mà chúng tạo ra sẽ không được cập nhật trong một số trường hợp nhất định (như hộp giới hạn trên các đối tượng văn bản khi thay đổi kích thước trục), nhưng điều đó có thể được tính đến với việc triển khai hướng đối tượng hoàn chỉnh hơn liên quan đến việc kế thừa từ tay cầm lớp học , sử dụng các sự kiện và người nghe , vv Bây giờ, đây là những triển khai đơn giản hơn của tôi:

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 lòng.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

Và đây là một kịch bản mẫu sử dụng chúng để tái tạo truyện tranh ở trên. Tôi đã tạo lại các dòng bằng cách sử dụng ginputđể đánh dấu các điểm trong cốt truyện bằng chuột, bắt chúng, sau đó vẽ chúng theo cách tôi muốn:

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

(kèn) đây là cốt truyện kết quả!:

nhập mô tả hình ảnh ở đây


2
Tuyệt vời! Nhận xét duy nhất của tôi là các dòng trỏ từ văn bản nên mỏng hơn và cong hơn (ít gượng gạo hơn).
bla

4
Điều này là tuyệt vời, mặc dù cốt truyện bị bí danh. Tôi đã viết một bài viết ngắn về cách đối phó với vấn đề đó tại đây: hugocarr.com/index/xkcd-style-graphs-in-matlab
Huguenot

28

Được rồi, đây là nỗ lực ít thô thiển nhưng vẫn chưa hoàn toàn của tôi:

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

Kết quả:

XKCD giả trong Matlab

Những việc cần làm:

  1. Tìm các chức năng tốt hơn (xác định rõ hơn chúng là khôn ngoan)
  2. Thêm "chú thích" và đường lượn sóng vào các đường cong mà chúng mô tả
  3. Tìm một phông chữ tốt hơn Comic Sans!
  4. Tổng quát hóa mọi thứ thành một hàm plot2xkcdđể chúng ta có thể chuyển đổi bất kỳ cốt truyện / hình nào sang kiểu xkcd.

1
Công việc tốt đẹp với màu sắc và trục! Mặc dù vậy, tôi cảm thấy rằng họ hơi quá bồn chồn. +1 dù sao đi nữa.
Jonas

@HighPerormanceMark: Tôi vẫn không nghĩ rằng điều này rất hữu ích, tuy nhiên, nó rất vui :)
Rody Oldenhuis

@RodyOldenhuis tại sao không hữu ích? Tôi tìm thấy các lô theo kiểu tìm kiếm tốt hơn so với các lô ban đầu. Thêm phong cách chắc chắn là một chức năng hợp lệ.
slayton

2
@slayton: Chúng ta hãy sử dụng một công cụ crunching số rất tiên tiến được thiết kế để siêu hiệu quả, có khả năng tạo ra các lô đẹp, sẵn sàng xuất bản chính xác nhất có thể và hãy sử dụng nó để tạo ... ** truyện tranh ** với nó . Xin lỗi, điều đó thật ngớ ngẩn. Đó là niềm vui lớn tuy nhiên, đó là lý do tại sao hầu hết mọi người ở đây bỏ phiếu tán và những gì có câu hỏi mở lại. Điều này sẽ được sử dụng cho khách truy cập trong tương lai? Vâng ... nó không truyền cảm hứng. Có lẽ nó sẽ mời một số người học Matlab. Nhưng để làm cho phong cách xkcd hoạt động đúng cách sẽ yêu cầu hack và các kỹ thuật ít nhất là ... đáng nghi ngờ :)
Rody Oldenhuis

6
@RodyOldenhuis: Tôi, với một người, sẽ sử dụng các biểu đồ này trong các bài thuyết trình của tôi. Và thông thường với "hack" mà bạn thực sự tìm hiểu cách môi trường hoạt động.
Jonas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.