function nodenum=ApplyPointBCs(fighandle, PointBCinfo)
% function nodenum=ApplyPointBCs(fighandle, POS, code, tang, norm, ang)
% ApplyPointBCs(FIGHANDLE, POS, CODE, TANG, NORM, ANG)
%
% This function accepts the handle to the main GUI figure (FIGHANDLE),
% the position (POS) and type (CODE) of a point boundary condition, the
% tangential (TANG) and normal (NORM) components of the boundary condition,
% and the angle (ANG) between the local and global coordinate systems. It
% then updates the handles.bcsi structure to reflect the boundary condition
% defined. Output is the node number where the boundary condition is
% actually applied.

% get handles and nodal coordinates
handles=guidata(fighandle);
xcors=handles.mesh.xcoords;
ycors=handles.mesh.ycoords;

% unpack PointBCinfo
POS =PointBCinfo(1:2);
pcode=PointBCinfo(3);
ptang=PointBCinfo(4);
pnorm=PointBCinfo(5);
pang =PointBCinfo(6);

% find the node closest to POS
dist=sqrt((xcors-POS(1)).^2+(ycors-POS(2)).^2);
[junk,closenode]=min(dist);
nodenum=closenode(1);

% based on this Point BC and any existing Surface BCs, correctly identify
% the code, angle, normal, and tangential components of the BC

% first find any existing BCs
scode=handles.bcsi.bccodes(nodenum);
sang =handles.bcsi.bcnangles(nodenum);
stang=handles.bcsi.bcboundts(nodenum);
snorm=handles.bcsi.bcboundns(nodenum);

% resolve point and surf BCs into each other's coordinate systems
theta=sang-pang; ct=cos(theta); st=sin(theta);
R=[ct, st; -st, ct];
prt=R*[ptang;0]; prn=R*[0;pnorm];
srt=R'*[stang;0]; srn=R'*[0;snorm];

% now consider different cases
if (pcode==4)||(scode==0) % point BC overrides surface BC
    code=pcode; ang=pang; tang=ptang; norm=pnorm;
elseif (scode==4) % surface BC overrides point BC
    code=scode; ang=sang; tang=stang; norm=snorm;
elseif (pcode==1) % point BC is a pure force and just adds to surf BC
    switch scode
        case 1 % both forces - just add
            code=scode; ang=sang; tang=stang+prn(1)+prt(1); norm=snorm+prn(2)+prt(2);
        case 2 % normal disp - ignore normal point BC
            code=scode; ang=sang; tang=stang+prn(1)+prt(1); norm=snorm;
        case 3 % tang disp - ignore tang point BC
            code=scode; ang=sang; tang=stang; norm=snorm+prn(2)+prt(2);
        otherwise
            error('slipped through the cracks');
    end
elseif (scode==1) % surf BC is pure force and just adds to point BC
    switch pcode
        case 2 % normal disp - ignore normal point BC
            code=pcode; ang=pang; tang=ptang+srn(1)+srt(1); norm=pnorm;
        case 3 % tang disp - ignore tang point BC
            code=pcode; ang=pang; tang=ptang; norm=pnorm+srn(2)+srt(2);
        otherwise
            error('slipped through the cracks');
    end
else % angles must align between point and surf BCs
    theta=sang-pang; ang=sang;
    if abs(theta)<(1e-8)
        Ncode=pcode; Nnorm=pnorm; Ntang=ptang;
    elseif abs(theta-pi/2)<(1e-8)
        Ncode=floor(6/pcode); Nnorm=-ptang; Ntang=pnorm;
    elseif abs(theta+pi/2)<(1e-8)
        Ncode=floor(6/pcode); Nnorm=ptang; Ntang=-pnorm;
    elseif abs(theta+pi)<(1e-8)
        Ncode=pcode; Nnorm=-pnorm; Ntang=-ptang;
    else
        error(['Angle mismatch. Boundary condition angle is',num2str(sang)]);
    end
    switch Ncode
        case 2
            switch scode
                case 2
                    code=scode; norm=Nnorm; tang=Ntang+stang;
                case 3
                    code=4; norm=Nnorm; tang=stang;
            end
        case 3
            switch scode
                case 2
                    code=4; norm=snorm; tang=Ntang;
                case 3
                    code=scode; norm=Nnorm+snorm; tang=Ntang;
            end
    end
    error('slipped through the cracks');
end
handles.bcsi.bccodes(nodenum)=code;
handles.bcsi.bcnangles(nodenum)=ang;
handles.bcsi.bcboundts(nodenum)=tang;
handles.bcsi.bcboundns(nodenum)=norm;

% save this point BC in the handles.bcsi struct
if isfield(handles.bcsi,'pointbcs')
    numpbcs=size(handles.bcsi.pointbcs,1)+1;
else
    handles.bcsi.pointbcs=[];
    numpbcs=1;
end
handles.bcsi.pointbcs(numpbcs,:)=PointBCinfo;
% handles.bcsi.pointbcs(numpbcs,:)=[POS(1) POS(2) code tang norm ang];

% update handles structure
guidata(fighandle,handles);