% Questa funzione rappresenta il caso ideale di SVM in cui ad ogni
% spostamento dei punti in esame viene effettuato un nuovo TRAIN.
% INPUT --> dinamica dei punti (complessiva e relativa, punti rossi e punti
% blu) + etichette iniziali ad essi assegnate
% OUTPUT --> stati ottenuti ad ogni ciclo + distanze minime SV/retta
% (iperpiano ottimale)

function [beta_tot dist_min] = fun_ideale(P,P_r,P_b,y_label)

global N t n_f x pp
addpath('libsvm-mat-3.0-1');

%% Inizializzazione parametri di OUTPUT della funzione
beta_tot = [];
dist_min = [];

% comando utilizzato per la creazione del video della sequenza
% --> aviobj = avifile('movim_punti.avi','fps',5);

%% SVM TRAIN
% ad ogni ciclo viene eseguito un nuovo training sui punti rossi e blu e
% viene cercato l'iperpiano ottimo che meglio divide i due gruppi. Inoltre
% per ogni t vengono evidenziati i relativi support vector (SV)

for t = 1:N
    
    model = svmtrain(y_label,P(:,1:2,t),'-t 0');
    
    % calcolo iperpiano ottimo
    beta_0 = -model.rho;
    beta = zeros(n_f,1);
    N_sv = model.totalSV;
    sv_tmp = zeros(N_sv,n_f);

    for s = 1:N_sv
        for q = 1:n_f
            sv_tmp(s,q) = model.SVs(s,q);
        end
    	beta = beta + model.sv_coef(s)*sv_tmp(s,:)';
    end

    b_ott = [beta; beta_0];
    retta = -(b_ott(1)/b_ott(2)*x + b_ott(3)/b_ott(2));
    m1 = -(b_ott(1)/b_ott(2));      % coefficiente angolare
    
    % memorizzazione del nuovo stato ottenuto 
    beta_tot = [beta_tot b_ott];
    
    x_min_1 = sv_tmp(1,:);
    x_min_2 = sv_tmp(2,:);
    
    % calcolo della distanza punto/retta di ogni SV 
    % si evidenziano in verde i SV
    % distanza punto/retta --> |ax + by + c|/sqrt(a^2 + b^2)
    % dove (x,y) sono le coordinate del punto considerato
    % e a,b,c sono i coefficienti della retta in esame
    b = b_ott;
    d_min_1 = abs(b(1)*sv_tmp(1,1) + b(2)*sv_tmp(1,2) + b(3))/sqrt(b(1)^2 + b(2)^2);
    d_min_2 = abs(b(1)*sv_tmp(2,1) + b(2)*sv_tmp(2,2) + b(3))/sqrt(b(1)^2 + b(2)^2);
    
    % memorizzazione delle distanze minime relative ottenute ad ogni passo
    dist_min = [dist_min; d_min_1 d_min_2];
        
    % margini SVM (rette parallele all'iperpiano ottimo, passanti per i
    % punti a distanza minima calcolati sopra)
    % se vi sono più di 2 SV bisogna fare attenzione a prendere i due
    % margini dei due differenti gruppi di punti
    if length(sv_tmp) > 2
        margine1 = m1*(x - sv_tmp(1,1)) + sv_tmp(1,2);    % rosso
        margine2 = m1*(x - sv_tmp(3,1)) + sv_tmp(3,2);    % blu
    else
        margine1 = m1*(x - sv_tmp(1,1)) + sv_tmp(1,2);    % rosso
        margine2 = m1*(x - sv_tmp(2,1)) + sv_tmp(2,2);    % blu
    end
    
    % calcolo distanze sv/iperpiano
    x_perp1 = (b_ott(2)^2*x_min_1(1) - b_ott(1)*b_ott(2)*x_min_1(2) - b_ott(3)*b_ott(1))/(b_ott(1)^2+b_ott(2)^2);
    y_perp1 = m1*x_perp1 - b_ott(3)/b_ott(2);
    x_perp2 = (b_ott(2)^2*x_min_2(1) - b_ott(1)*b_ott(2)*x_min_2(2) - b_ott(3)*b_ott(1))/(b_ott(1)^2+b_ott(2)^2);
    y_perp2 = m1*x_perp2 - b_ott(3)/b_ott(2);
    
    
    % plot punti in esame (rossi e blu)
    figure(1)
    plot(P_r(:,1,t),P_r(:,2,t),'o','MarkerEdgeColor','r','MarkerFaceColor','r');
    hold on
    title('Algoritmo ideale','fontsize',12)
    plot(P_b(:,1,t),P_b(:,2,t),'o','MarkerEdgeColor','b','MarkerFaceColor','b');
    axis([-200 300 -200 300])
    grid on
    pause(pp)
    hold on
    
    % plot SV + iperpiano ottimo + margini
    plot(sv_tmp(:,1),sv_tmp(:,2),'o','MarkerEdgeColor','g','MarkerFaceColor','g');
    plot(x,retta,'k');
    plot(x,margine1,'--g','LineWidth',1);
    plot(x,margine2,'--g','LineWidth',1);
    plot([x_min_1(1) x_perp1],[x_min_1(2) y_perp1],'--');
    plot([x_min_2(1) x_perp2],[x_min_2(2) y_perp2],'--');
    pause(pp)
    hold off
    
    % comandi utilizzati per la creazione del video della sequenza
    % --> fig = figure(t);
    % --> F = getframe(fig);
    % --> aviobj = addframe(aviobj,F);

    
end

% comando utilizzato per la creazione del video della sequenza
% --> aviobj = close(aviobj);
