% detectcollision1.m
% detect the collision between a particle and obstructions
% particle center moves from (x1,y1) to (x2,y2) in a line
% particle is represented with a circle (radius = r)
% obstructions are defined in matrix 'elems', element=0: obstruction, element=1: void space
% output: ifcollide, 0: no collision, 1: collision
function ifcollide = detectcollision1(x1,y1,x2,y2,r,elems)
% upper boundary
[uby ubx]=size(elems);
uby=uby-1;
ubx=ubx-1;
% moving direction in x
sgndx=sign(x1-x2);
ifcollide=0;
if sgndx~=0
    % equation of the trajectory of particle center: y=ax+c
    a=(y2-y1)/(x2-x1);
    c=-a*x1+y1;
    sintheta=sqrt(a^2/(a^2+1));
    costheta=sqrt(1/(a^2+1));
    % equation of the perpendicular line: x==-ay+d
    d=(x1+x2)/2+a*(y1+y2)/2;
    halfdist=sqrt((x2-x1)^2+(y2-y1)^2)/2;
    % y limits
    maxy=floor(max(y2,y1)+r*costheta);
    miny=floor(min(y2,y1)-r*costheta);   
    % x limits
    x2ext=floor(x2-sgndx*r*sintheta);
    x1ext=floor(x1+sgndx*r*sintheta);   
   
    if a>0
        % detect collision from the trajectory of particle transverse
        % diameter (a rectangular)
        for xtrack=x2ext:sgndx:x1ext
            for ytrack=max(miny,ceil(xtrack*a+c-1-r/costheta)):min(maxy,floor((xtrack+1)*a+c+r/costheta))
                if xtrack>=-a*(ytrack+1)+d-1-halfdist/costheta && xtrack<=-a*ytrack+d+halfdist/costheta
                    if xtrack<0 || xtrack>ubx || ytrack<0 || ytrack>uby || elems(ytrack+1,xtrack+1)==0
                        ifcollide=1;
                        return
                    end
                end
            end
        end
       
        % detect collision from the half circle at the end of trajectory
        for ysurcir=floor(y2-r):floor(y2+r)               
            if ysurcir>maxy || ysurcir<miny
                xsurcirs=floor(x2-r):floor(x2+r);
            else
                if sgndx==1
                    xsurcirs=floor(x2-r):max(x2ext-1,floor(-a*(ysurcir+1)+d-1-halfdist/costheta));
                else
                    xsurcirs=min(x2ext+1,ceil(-a*ysurcir+d+halfdist/costheta)):floor(x2+r);
                end
            end
            for xsurcir=xsurcirs
                dmin=0;
                if x2<xsurcir
                    dmin=dmin+(xsurcir-x2)^2;
                elseif x2>xsurcir+1
                    dmin=dmin+(xsurcir+1-x2)^2;
                end
                if y2<ysurcir
                    dmin=dmin+(ysurcir-y2)^2;
                elseif y2>ysurcir+1
                    dmin=dmin+(ysurcir+1-y2)^2;
                end
                if dmin<=r^2
                    if xsurcir<0 || xsurcir>ubx || ysurcir<0 || ysurcir>uby || elems(ysurcir+1,xsurcir+1)==0 || elems(ysurcir+1,xsurcir+1)==0
                        ifcollide=1;
                        return
                    end
                end
            end
        end
    else
        for xtrack=x2ext:sgndx:x1ext
            for ytrack=max(miny,ceil((xtrack+1)*a+c-1-r/costheta)):min(maxy,floor(xtrack*a+c+r/costheta))
                if xtrack>=-a*ytrack+d-1-halfdist/costheta && xtrack<=-a*(ytrack+1)+d+halfdist/costheta
                    if xtrack<0 || xtrack>ubx || ytrack<0 || ytrack>uby || elems(ytrack+1,xtrack+1)==0
                        ifcollide=1;
                        return
                    end
                end 
            end
        end
       
        for ysurcir=floor(y2-r):floor(y2+r)               
            if ysurcir>maxy || ysurcir<miny
                xsurcirs=floor(x2-r):floor(x2+r);
            else
                if sgndx==1
                    xsurcirs=floor(x2-r):max(x2ext-1,floor(-a*ysurcir+d-1-halfdist/costheta));
                else
                    xsurcirs=min(x2ext+1,ceil(-a*(ysurcir+1)+d+halfdist/costheta)):floor(x2+r);
                end
            end
            for xsurcir=xsurcirs
                dmin=0;
                if x2<xsurcir
                    dmin=dmin+(xsurcir-x2)^2;
                elseif x2>xsurcir+1
                    dmin=dmin+(xsurcir+1-x2)^2;
                end
                if y2<ysurcir
                    dmin=dmin+(ysurcir-y2)^2;
                elseif y2>ysurcir+1
                    dmin=dmin+(ysurcir+1-y2)^2;
                end
                if dmin<=r^2
                    if xsurcir<0 || xsurcir>ubx || ysurcir<0 || ysurcir>uby || elems(ysurcir+1,xsurcir+1)==0 || elems(ysurcir+1,xsurcir+1)==0
                        ifcollide=1;
                        return
                    end
                end
            end
        end
    end
else
    sgndy=sign(y1-y2);
    if sgndy~=0
        for ytrack=floor(y2):sgndy:floor(y1)
            for xtrack=floor(x1-r):floor(x1+r)
                if ytrack<0 || ytrack>uby || elems(ytrack+1,xtrack+1)==0
                    ifcollide=1;
                    return
                end
            end
        end
       
        for xsurcir=floor(x1-r):floor(x1+r)
            if sgndy==1
                ysurcirs=floor(y2-r):(floor(y2)-1);
            else
                ysurcirs=ceil(y2):floor(y2+r);
            end
            for ysurcir=ysurcirs
                dmin=0;
                if x2<xsurcir
                    dmin=dmin+(xsurcir-x2)^2;
                elseif x2>xsurcir+1
                    dmin=dmin+(xsurcir+1-x2)^2;
                end
                if y2<ysurcir
                    dmin=dmin+(ysurcir-y2)^2;
                elseif y2>ysurcir+1
                    dmin=dmin+(ysurcir+1-y2)^2;
                end
                if dmin<=r^2
                    if ysurcir<0 || ysurcir>uby || elems(ysurcir+1,xsurcir+1)==0
                        ifcollide=1;
                        return
                    end
                end
            end
        end
    end
end