MATLAB - NOWY TYP RYSUNKU - WYPEŁNIENIE

Zadanie na dzisiaj jest bardzo proste. Uzyskać w MATLABie taki rysunek jak poniżej: wypełniony obszar, ograniczony „od góry” i „od dołu” dowolną krzywą. Nie ma takiej funkcji w MATLABie? Napiszemy ją sami!

Jak pewnie się domyślacie, w powyższym stwierdzeniu jest nieco ironii. Okazuje się bowiem, że w MATLABie nie ma (!) funkcji, która wprost, potrafi taki rysunek stworzyć.

Tło problemu

Konieczność stworzenia obszarów wypełnionych dowolnym kolorem, które są ograniczone przez dwie krzywe, zrodziła się na potrzeby wizualizacji zależności błędów pomiarowych. Błędy takie obrazują przedziały wartości (Y) dla danej wartości wielkości mierzonej (X). Oczywiście to tylko przykład, a problem można uogólnić na inne przypadki wykresów.

Załóżmy więc ogólnie, że mamy trzy wektory: x – wektor argumentów (oś X), y1g i y1d -  dwa wektory zawierające wartości dla dwóch krzywych ograniczających rysowany obszar.

Podejście pierwsze – funkcja area

Naturalnym wyborem aby uzyskać powyższy rysunek wydaje się funkcja area MATLABa. Działa ona podobnie do funkcji plot, ale obszar pomiędzy wykresem krzywej, a osią X układu współrzędnych jest wypełniana kolorem. Tutaj można pobrać dane do wykresu.

clear all; close all; clc

load dane1

figure; 
Y = [y1g; y1d]';
area(x, Y); grid on;
xlabel('X'); ylabel('Y')

Coś jednak poszło nie tak… Funkcja area wypełnia obszar między krzywą a osią X. Ewentualnie, można podać parametr basevalue, który określa rzędną, do której ma nastąpić wypełnienie (np. wpisując basevalue = -5, wypełnienie nie nastąpi do osi X tylko do prostej równoległej do osi X położonej na poziomie -5). To oznacza, że funkcja area, nie sprawdzi się w tym przypadku.

Podejście drugie – funkcja fill

W bazie funkcji graficznych MATLABa, na próżno szukać takiej, która poradzi sobie wprost z naszym problemem. Jednak przeglądając „helpa”, natrafiłem na funkcję fill. Jak czytamy w opisie funkcji: „rysuje ona wypełnione wielokąty o wierzchołkach we współrzędnych (x,y)”. Ok… brzmi to dobrze.. spróbujmy zatem użyć tej funkcji.

figure; 

f = fill(x,y1g,'green');
f.FaceColor = [0.6 1 0.6];      
f.EdgeColor = [0.3 1 0.3]; 
f.LineWidth = 2;

hold on;
f = fill(x,y1d,'green');
f.FaceColor = [0.6 1 0.6];      
f.EdgeColor = [0.3 1 0.3]; 
f.LineWidth = 2;

grid on;
xlabel('X'); ylabel('Y')

No bardzo pięknie… Dostaliśmy samolocik z papieru 🙂 Widać co prawda kształt ograniczających krzywych, ale obszar jest wypełniony jakby „na zewnątrz”. Wynika to z faktu, że funkcja fill, łączy ostatni wierzchołek wielokąta z pierwszym. Aby poprawnie wypełnić interesujący nas obszar musimy dodać dwa punkty więcej do wykresu:

figure; 
X = [x(1), x, x(end)]; 
Y = [mean([y1g(1) y1d(1)]), y1g  mean([y1g(1) y1d(1)])];
f = fill(X,Y,'green');
f.FaceColor = [0.6 1 0.6];      
f.EdgeColor = [0.3 1 0.3]; 
f.LineWidth = 2;

hold on;

X = [x(1), x, x(end)]; 
Y = [5, y1d  5];
f = fill(X,Y,'green');
f.FaceColor = [0.6 1 0.6];      
f.EdgeColor = [0.3 1 0.3]; 
f.LineWidth = 2;

grid on;
xlabel('X'); ylabel('Y')

Po tej całej gimnastyce udało się uzyskać (prawie) satysfakcjonujący efekt. Jednak program nie jest zbyt elegancki. Składa się z dwóch rysunków sklejanych w jeden i to widać wzdłuż osi X. Czy da się to zrobić bardziej efektywnie? Tak, program i końcowy rysunek jest poniżej:


figure; 
X = [x(1), x, x(end:-1:1), x(1)]; 
Y = [mean([y1g(1) y1d(1)]), y1g y1d(end:-1:1), mean([y1g(1) y1d(1)])];
f = fill(X,Y,'green');
f.FaceColor = [0.6 1 0.6];      
f.EdgeColor = [0.3 1 0.3]; 
f.LineWidth = 2;

xlabel('X'); ylabel('Y')
grid on; 
Funkcja

Właśnie stworzyliśmy nowy rodzaj rysunku w MATLABie. Na podstawie powyższego programu warto napisać funkcje, którą będzie można wygodnie wywoływać ilekroć będziemy chcieli uzyskać wypełnienie wykresu. Funkcja przyjmuje jako argumenty, wektory x, yd i yg, a ponadto kolor - zmienna określająca kolor wypełnienia, ekolor - kolor linii, grubosc - grubość linii. Oczywiście nie ma we funkcji obsługi błędów, itp. Możecie te funkcję sami rozbudować:

function f = fig_fill(x, yd, yg, kolor, ekolor, grubosc)

X = [x(1), x, x(end:-1:1), x(1)]; 
Y = [mean([yg(1) yd(1)]), yg yd(end:-1:1), mean([yg(1) yd(1)])];
f = fill(X,Y,'green');
f.FaceColor = kolor;      
f.EdgeColor = ekolor; 
f.LineWidth = grubosc;

A poniżej przykłady efektów jakie można uzyskać stosują naszą funkcję fig_fill:

(Visited 44 times, 1 visits today)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *