2016-03-17 19 views
9

Mam okrągłą kratownicę, a na stronach kraty rysuję znormalizowane strzałki, które pozostają w tej samej wielkości i zmieniają kierunek zgodnie z symulacją, której szczegóły nie mają znaczenia.Wymień strzały z kołczanu na obrazy

Moi działki wyglądać następująco

enter image description here

Czy to możliwe, aby zastąpić strzałkę w działce kołczan przez jpg/bmp/​​GIF/PNG? lub jakimkolwiek innym poleceniem?

Idealnie byłoby to wyglądać mniej więcej tak (choć niekoniecznie strzałkami)

enter image description here

+0

[W] (http://stackoverflow.com/questions/18214874/how-to-draw-good-looking-arrows-in-matlab) może pomóc. Aby uzyskać najlepsze wyniki, zaleciłbym samodzielne wykonanie rysowania. – horchler

Odpowiedz

27

Wyjaśnienie

Jednym ze sposobów, że można to zrobić, byłoby użyć surface object z texture-map as the FaceColor.

W programie MATLAB można utworzyć prostą prostokątną powierzchnię. Można ustawić wartość FaceColor na texturemap, która spowoduje, że wartość przypisana do CData zostanie odwzorowana na powierzchnię.

Następnie, aby uzyskać przezroczystość, można również ustawić wartość FaceAlpha na texturemap i ustawić wartość AlphaData, a wartości przezroczystości będą odwzorowane również w zakresie powierzchni.

Aby zastosować to do swojej skrzynki, chcesz ustawić CData na obraz, który chcesz zastąpić strzałkami. I chcesz, aby rozmiar AlphaData był taki sam, jak danych obrazu o wartości 1, w której ma być nieprzezroczysty i 0, w którym ma być przezroczysty. Dzięki temu nie będzie wyglądać jak obraz, który opublikowałeś, gdzie wyraźnie widać ramkę obwiedni. Następnie musisz narysować jedną z tych powierzchni, na którą pójdzie każda ze strzałek, i skalować/pozycjonować ją odpowiednio.

Realizacja

Aktualizacja: Bardziej dopracowana wersja tego kodu (ImageQuiver) jest teraz dostępny na Github jak również MATLAB File Exchange.

Jako demonstrację tego, o czym mówię, stworzyłem następującą funkcję, która w zasadzie właśnie to robi. Przyjmuje te same dane wejściowe, co quiver (z danymi obrazu dostarczanymi jako pierwsze i opcjonalnym parametrem AlphaData na końcu) i tworzy powierzchnię dla wszystkich żądanych współrzędnych wskazujących w żądanym kierunku i skaluje się o określoną wartość.

function h = quiverpic(im, X, Y, dX, dY, scale, alpha) 
    % im - RGB or indexed image 
    % X - X positions 
    % Y - Y positions 
    % dX - X direction vector 
    % dY - Y direction vector 
    % scale - Any scaling (Default = 1) 
    % alpha - Transparency (same size as im), if not specified = ~isnan(im) 

    h = hggroup(); 

    if ~exist('scale', 'var') 
     % By default there is no scaling 
     scale = 1; 
    end 

    if ~exist('alpha', 'var') 
     % By default, any NaN will be transparent 
     alpha = ~isnan(im); 
    end 

    % Determine aspect ratio of the source image 
    width_to_height = size(im, 2)/size(im, 1); 

    for k = 1:numel(X) 
     % Determine angle from displacement vectors 
     theta = atan2(dY(k), dX(k)); 

     % Subtract pi/2 to +y is considered "up" 
     theta = theta + pi/2; 

     % Setup surface plot boundary 
     [xx,yy] = meshgrid([-0.5, 0.5] * width_to_height, [0 1]); 

     % Scale depending on magnitude of dX and dY 
     this_scale = scale * sqrt(dX(k).^2 + dY(k).^2); 

     % Scale X and Y components prior to rotating 
     xx = xx .* this_scale; 
     yy = yy .* this_scale; 

     % Rotate to align with the desired direction 
     xdata = xx .* cos(theta) - yy .* sin(theta); 
     ydata = xx .* sin(theta) + yy .* cos(theta); 

     % Determine what is considered the "anchor" of the graphic. 
     % For now this is assumed to be the "bottom-middle" 
     xoffset = X(k) - mean(xdata(2,:)); 
     yoffset = Y(k) - mean(ydata(2,:)); 

     % Actually plot the surface. 
     surf(xdata + xoffset, ... 
      ydata + yoffset, zeros(2), ... 
      'Parent', h, ... 
      'FaceColor', 'texture', ... 
      'EdgeColor', 'none', ... 
      'CData', im, ... 
      'FaceAlpha', 'texture', ... 
      'AlphaData', double(alpha)); 
    end 
end 

Przykład

napisałem mały skrypt testowy, aby pokazać, jak to może być stosowane i aby pokazać wyniki.

t = linspace(0, 2*pi, 13); 
dX = cos(t(1:end-1)); 
dY = sin(t(1:end-1)); 
X = (3 * dX) + 5; 
Y = (3 * dY) + 5; 
scale = 1; 

% Load the MATLAB logo as an example image 
png = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif'); 
[im, map] = imread(png); 
im = ind2rgb(im, map); 

% Determine alpha channel based on upper left hand corner pixel 
flatim = reshape(im, [], 3); 
alpha = ~ismember(flatim, squeeze(im(1,1,:)).', 'rows'); 
alpha = reshape(alpha, size(im(:,:,1))); 

% Plot some things prior to creating the quiverpic object 
fig = figure(); 
hax = axes('Parent', fig); 
axis(hax, 'equal'); 

% Plot a full circle 
t = linspace(0, 2*pi, 100); 
plot((cos(t) * 3) + 5, (sin(t) * 3) + 5, '-') 

hold(hax, 'on') 

% Plot markers at all the quiver centers 
plot(X, Y, 'o', 'MarkerFaceColor', 'w') 

% Plot a random image behind everything to demonstrate transparency 
him = imagesc(rand(9)); 
uistack(him, 'bottom') 

axis(hax, 'equal') 
colormap(fig, 'gray') 
set(hax, 'clim', [-4 4]); 

% Now plot the quiverpic 
h = quiverpic(im, X, Y, dX, dY, 1, alpha); 

axis(hax, 'tight') 

Wyniki

enter image description here

absurd

sam obraz z różnych kierunków i skalowanie

enter image description here

dowolny obraz z dowolnej proporcji obrazu będzie działać dobrze

enter image description here