clear all;

% Parameters
re_i = -5;
re_f = 5;
im_i = -5;
im_f = 5;
steps = 0.05;

% The functions
RE_f = @(x, y) x.^2-y.^2;
IM_f = @(x, y) 2.*x.*y;

% A cool curve gamma
ct = -pi:steps:pi/2;
cx = 4*cos(ct);
cy = 4*sin(ct).*log(abs(ct));

plotGraph("Realteil von f(z)", RE_f, cx, cy, re_i, re_f, im_i, im_f, steps);
plotGraph("Imaginärteil von f(z)", IM_f, cx, cy, re_i, re_f, im_i, im_f, steps);

% Vector field
[X,Y] = meshgrid(re_i:0.5:re_f,im_i:0.5:im_f);
figure;
quiver(X, Y, RE_f(X, Y), IM_f(X, Y));
title("Vektorfeld von f(z)");
xlabel("Re(z)");
ylabel("Im(z)");
xlim([re_i, re_f]);
ylim([im_i, im_f]);

% Plot the curve gamma
figure;
plot(cx, cy, 'b', 'LineWidth', 2);
title("Weg $\gamma$", 'interpreter','latex');
xlabel("Re(z)");
ylabel("Im(z)");
grid on;

function plotGraph(name, Function, cx, cy, re_i, re_f, im_i, im_f, st)
    [X,Y] = meshgrid(re_i:st:re_f,im_i:st:im_f);

    % Plots 
    figure;
    % The surface
    surf(X, Y, Function(X, Y), 'LineStyle','none', 'FaceAlpha', 0.8);
    hold on;
    title(name);
    xlabel("Re(z)");
    ylabel("Im(z)");
    xlim([re_i, re_f]);
    ylim([im_i, im_f]);
    plot3(cx, cy, Function(cx, cy), 'b', 'LineWidth', 2);
    plot3(cx, cy, zeros(1, length(cx)), 'b', 'LineWidth', 2);

    index = 1;
    tri = [];
    point = [];
    for i = drange(1, length(cx) - 1)
        % A veeery inefficient way of doing this :( (but it works xD)
        point = [point; cx(i), cy(i), 0];
        point = [point; cx(i+1), cy(i+1), 0];
        point = [point; cx(i), cy(i), Function(cx(i), cy(i))];
        point = [point; cx(i+1), cy(i+1), Function(cx(i+1), cy(i+1))];

        new_tri = [index, index + 2, index + 1; index + 1, index + 2, index + 3];
        tri = [tri; new_tri];
        index = index + 4;
    end

    tr = triangulation(tri, point);
    trisurf(tr, 'FaceAlpha', 0.8);
end