function z_vals = plot3DCost(theta0_vals, theta1_vals, J_vals)
    figure;
    surf(theta0_vals, theta1_vals, J_vals', 'EdgeColor', 'none');
    xlabel('Theta 0'); 
    ylabel('Theta 1');
    zlabel('Cost J');
    title('Cost function as a function of theta values');
    view(-40, 30);
    axis([-5000 5000 0 100 min(min(J_vals)) max(max(J_vals))]);
    z_vals = linspace(min(min(J_vals)), max(max(J_vals)), 20); % 20 planes
    
    hold on;
    for z = z_vals
        [X_plane, Y_plane] = meshgrid(theta0_vals, theta1_vals);
        Z_plane = z * ones(size(X_plane));
        surf(X_plane, Y_plane, Z_plane, 'FaceColor', 'g', 'FaceAlpha', 0.4, 'EdgeColor', 'none');
        pause(0.3);
    end
    hold off;
end

function plotContourWithGD(theta0_vals, theta1_vals, J_vals, theta_path, z_vals)
    figure;
    contour(theta0_vals, theta1_vals, J_vals', z_vals, 'LineWidth', 2);
    xlabel('Theta 0');
    ylabel('Theta 1');
    title('Contours of intersection between planes and the cost function');
    colorbar;
    
    hold on;
    plot(theta_path(1,:), theta_path(2,:), 'r-o', 'LineWidth', 2, 'MarkerSize', 5);
    legend('Contours', 'Gradient Descent Path');
    hold off;
end
