% Input:
% A: Matrix (A from A*x <= b describing the guard to calculate the
%            intersection with)
% b: vector (b from A*x <= b describing the guard to calculate the
% intersection with)
% L: Matrix (containing row-wise direction vectors)
% Ijump: vector (containing the ids of the sets to calculate the
%                intersection with)
% omegas: cell array of function handles (support functions)
% algo: String 'fminbnd/fminsearch/fminunc/fmincon/dichotomicSearch/optimizedDichotomicSearch'
% options: cell array (as described in hybridReachabilityAnalysis.m)
% results: matrix (containing the evaluation results of the flowpipe)
% equality: int (1 if the intersection regards an equality guard, 0 else)
% additional_dimension_constraints: vector

% Output:
% intersectedresults: Matrix (containing the evaluation results for the
% intersection)
% intersectedomegas: cell array of function handles (support functions of the intersection)

% Description:
% Computes and evaluates the sets which are the results of the intersection
% of the flowpipe with the guards of a transition

function [intersectedresults, intersectedomegas] = intersectFlowpipe(A,b,L,Ijump,omegas,algo,options,results,equality,additional_dimension_constraints)
global inf;

if ~isempty(A) % b may not be empty either
    
    construction =  strcmp(options{1},'Construction');
    intersectedomegas = [];

    if construction
        intersectedresults = [];
    end;

    if ~isempty(omegas)
        intersectedomegas = omegas(Ijump);
    end;

    %intersectedresults = zeros(size(L,1),length(Ijump));
    if ~isempty(results)
        intersectedresults = results(:,Ijump);

        accesssize = 1:size(intersectedresults,1);

        if ~isempty(additional_dimension_constraints)
            intersectedresults = [intersectedresults;repmat(additional_dimension_constraints,1,size(intersectedresults,2))];
            extendedL = [L; [zeros(2,size(L,2)-1) [1;-1] ]];
        end;
    end;

    if equality
        A = [A; -A];
        b = [b; -b];    
    end;

    if ~isempty(additional_dimension_constraints)
        % add constraints for additional dimension
        warning('off','MATLAB:catenate:DimensionMismatch');
        guard = calcPolytopeSP([L;A; zeros(2,size(A,2)-1) [1;-1]],[inf*ones(size(L,1),1);b;additional_dimension_constraints],options{2},options{3},zeros(size(A,2),1),[],[]);
        warning('on','MATLAB:catenate:DimensionMismatch');
    else
        guard = calcPolytopeSP([L;A],[inf*ones(size(L,1),1);b],options{2},options{3},zeros(size(A,2),1),[],[]);
    end;

    if ~construction
        % evaluate only in case the matrix representation is used
        guardevaluation = sptotemplatepolyhedra(guard,L);
    end;

    for i=1:1:size(Ijump,2)
        Snew = omegas{Ijump(i)};

        if strcmp(algo,'fast_intersection')

            intersectedomegas{i} = @(l) min(guard(l), Snew(l));

              if ~construction
                 intersectedresults(accesssize,i) = min(guardevaluation, intersectedresults(accesssize,i));
                 omega = calcPolytopeSP(extendedL,intersectedresults(:,i),options{2},options{3},zeros(size(L,2),1),[],[]);
                 intersectedresults(accesssize,i) = sptotemplatepolyhedra(omega,L);
              end;
        else
            for j=1:1:size(A,1)
                if strcmp(algo,'dichotomicSearch') || strcmp(algo,'optimizedDichotomicSearch')
                    [Snew,temp] = dimensionreduction(L,options{15},Snew,A(j,:)',b(j),algo,options);
                    intersectedresults(accesssize)= temp;
                else    
                        Snew = directintersection(Snew,A(j,:)',b(j),{algo});
                        intersectedomegas{i} = Snew;

                        if ~construction
                         intersectedresults(accesssize,i) = sptotemplatepolyhedra(Snew,L);
                        end;
                end;
            end;
        end;

    end;

    if ~isempty(intersectedresults) 
            intersectedresults = intersectedresults(accesssize,:);
    end;
else
    intersectedresults = results(:,Ijump);
    intersectedomegas = omegas(Ijump);
end;
