function PMTemplateBuilder(arg)
global AAMShapemodel_figure_handle
global AAMModelGenerator_handle
global AAMModelBuilder_handle
global AAMSetPicker_handle
global UpdateModel_handle
global PMTemplateBuilder_handle
global PDMWalk_handle

if strcmp(arg, 'init')
    if ~exist('Templates', 'dir')
        d = pwd;
        [v, d] = fileparts(pwd);
        if strcmp(d(1:4), 'PRJ_')
            mkdir('Templates');
        else
            error('Cannot find a valid Templates directory..exiting PMTemplateBuilder');
            return;
        end
    end
    % Open the GUI for display
    fig = openfig(mfilename, 'reuse');
    movegui(fig, 'center');
    set(fig, 'Visible', 'on');
    % Generate a structure of handles to pass to callbacks, and store
    Data.handles = guihandles(fig);
    set(fig, 'Color', get(Data.handles.uipanel8, 'BackgroundCOlor'));

    Data.handles.figMain = fig;
    PMTemplateBuilder_handle=fig;
    Data.handles.PointModelTemplate = PointModelTemplate;

    Data.handles.dat.plotH = [];
    Data.handles.dat.newTemplate = 0;

    Data.handles.dat.currentLoopNumber = 0;
    Data.handles.dat.currentLoop = [];
    Data.handles.dat.toSave = 0;
    Data.handles.dat.changedPointModels = 0;
    
    Data.handles.workingDir = pwd;
    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');

    DataMain = guidata(findobj('Tag', 'AAMToolbox'));
    Data.handles.PointModelTemplate = get(DataMain.handles.AAM, 'PointModelTemplate');
    % Now we should load the point models, if there are any.
    Data.handles.PointModels = LoadPointModels(Data.handles.PointModelTemplate);
    if ~isempty(get(Data.handles.PointModelTemplate, 'image'))
        set(Data.handles.mainAxes, 'Visible', 'off');
        cla(Data.handles.mainAxes);
        I=get(Data.handles.PointModelTemplate, 'image');
        if max(I(:))>1
            I=double(I)/255;
        end
        Data.handles.imagesize=size(I);
        imagesc(I, 'HitTest', 'off'); axis image ij;
        Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        Data.handles.workingDir = get(Data.handles.PointModelTemplate, 'direc');
        set(Data.handles.imageDirTxt, 'String', cut_string(get(Data.handles.PointModelTemplate, 'imageDir')));
        set(Data.handles.imageNameTxt, 'String', get(Data.handles.PointModelTemplate, 'imageName'));
        set(Data.handles.templateDirTxt, 'String', cut_string(get(Data.handles.PointModelTemplate, 'direc')));
        set(Data.handles.templateNameTxt, 'String', get(Data.handles.PointModelTemplate, 'name'));
    end
    guidata(fig, Data);
    if exist('AAMShapemodel_figure_handle')
        if ishandle(AAMShapemodel_figure_handle)
            set(AAMShapemodel_figure_handle,'visible','off');
        end
    end
    return;
else
    Data = guidata(gcbo);
    DataMain = guidata(findobj('Tag', 'AAMToolbox'));
    switch arg
        case 'ImportMeanPM'
            [Data.handles] = ImportMeanPM(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'ImportFromPM'
            [Data.handles] = ImportFromPM(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'ToggleLabeling'
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        case 'ToggleLandmarks'
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        case 'ToggleLines'
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);        
        case 'SaveTemplate'
            [Data.handles] = SaveTemplate(Data.handles);
        case 'ImportAndUpdate'
            [Data.handles] = ImportAndUpdate(Data.handles);
            Data.handles.dat.toSave = 1;            
        case 'LoadTemplate'
            [Data.handles] = LoadTemplate(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'LoadReplacementImage' 
            [Data.handles] = LoadReplacementImage(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'SmoothLandmarks'
            Data.handles = SmoothLandmarks(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'AddRemoveEdge'
            Data.handles = AddRemoveEdge(Data.handles);
            %Data.handles = SmoothLandmarks(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'SelectEdge'
            Data.handles = SelectEdge(Data.handles);
        case 'SelectTemplateImage'
            Data.handles = SelectTemplateImage(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'AddPoint'
            Data.handles = AddPoint(Data.handles);
            Data.handles.dat.toSave = 1;
            Data.handles.dat.changedPointModels = 1;
        case 'InsertPoint'
            Data.handles = InsertPoint(Data.handles);
            Data.handles.dat.toSave = 1;
            Data.handles.dat.changedPointModels = 1;
        case 'DeletePoints'
            Data.handles = DeletePoints(Data.handles);
            Data.handles.dat.toSave = 1;
            Data.handles.dat.changedPointModels = 1;
        case 'DeletePoint'
            Data.handles = DeletePoint(Data.handles);
        case 'DefinePrimaries'
            Data.handles = DefinePrimaries(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'TogglePrimary'
            Data.handles = TogglePrimary(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'MoveMode'
            Data.handles = MoveMode(Data.handles);
            Data.handles.dat.toSave = 1;
        case 'PointSelect'
            Data.handles = PointSelect(Data.handles);
        case 'MovePoint'
            % Moving the selected point
            Data.handles = MovePoint(Data.handles);
        case 'DropPoint'
            set(Data.handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
            Data.dat.PointToMove = [];
        case 'MovePointKeyPress'
            set(Data.handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
            set(Data.handles.movePointBtn, 'Value', 0);
            % Recall the move point function to enable the gui controls
            eval(sprintf('%s MoveMode', mfilename));
        case 'ToggleZoom'
            Data.handles = ToggleZoom(Data.handles);
        case 'TogglePan'
            Data.handles = TogglePan(Data.handles);
        case 'addLabel'
            Data.handles.dat.toSave = 1;
            Data.handles = addLabel(Data.handles);
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        case 'Done'
            if Data.handles.dat.toSave
                answer = questdlg('Do you want to save your template model before quitting?');
                switch answer
                    case 'Yes'
                        Data.handles = SaveTemplate(Data.handles);
                        if exist('AAMShapemodel_figure_handle')
                            if ishandle(AAMShapemodel_figure_handle)
                                set(AAMShapemodel_figure_handle,'visible','on');
                            end
                        end
                        delete(PMTemplateBuilder_handle);
                        AAMToolbox('refresh');
                        return;
                    case 'No'
                        if exist('AAMShapemodel_figure_handle')
                            if ishandle(AAMShapemodel_figure_handle)
                                set(AAMShapemodel_figure_handle,'visible','on');
                            end
                        end
                        delete(PMTemplateBuilder_handle);
                        AAMToolbox('refresh');
                        return;
                    otherwise
                        fprintf('You have selected a button that doesn''t exist');
                end
            else
                if exist('AAMShapemodel_figure_handle')
                    if ishandle(AAMShapemodel_figure_handle)
                        set(AAMShapemodel_figure_handle,'visible','on');
                    end
                end
                delete(PMTemplateBuilder_handle);
                AAMToolbox('refresh');
                return;
            end
        otherwise
            error('Unknown Option in PMTemplateBuilder');
    end
    if isfield(Data.handles, 'figMain')
        guidata(Data.handles.figMain, Data);
    end
    DataMain.handles.AAM = set(DataMain.handles.AAM, 'PointModelTemplate',Data.handles.PointModelTemplate);
    guidata(DataMain.handles.figMain, DataMain);
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
% ImportAndUpdate
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ImportAndUpdate(handles)
% Now we must give the option of all the point models and then perform and
% update.
files = dir('PointModels');
files = {files.name};
[s,v] = listdlg('PromptString','Select a Point Model Directory:','SelectionMode','single','ListString',files);
if v==0
    return;
end
pmdir = files{s};
pmfiles = dir(['PointModels', filesep, pmdir, filesep, '*_pm.mat']);
pmfiles = {pmfiles.name};
PointModels = [];
for f = 1:length(pmfiles)
    pts = load(['PointModels', filesep, pmdir, filesep, pmfiles{f}]);
    pts = pts.pts;
    pts = reshape(pts, 2, length(pts)/2);
    PointModels(f).name = ['PointModels', filesep, pmdir, filesep, pmfiles{f}];
    PointModels(f).pts = pts;
end
template = handles.PointModelTemplate;
template_pts = get(template, 'pts');
% Might need this if we want to rename a template.
% if size(template_pts,2) == size(PointModels(1).pts,2)
%     return;
% end
if size(template_pts,2) < size(PointModels(1).pts,2)
    uiwait(warndlg('There are fewer points in the template than in the point models, quitting.'));
    return;
end
new_pts = template_pts(:, size(PointModels(1).pts,2)+1:end);
pts = template_pts(:, 1:size(PointModels(1).pts,2));
loops = get(handles.PointModelTemplate, 'loops');
primaries = get(handles.PointModelTemplate, 'primaries');
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
CurrentPoint = CurrentPoint(1, 1:2)';
pointModels = PointModels;

for i=1:size(new_pts,2)
    x = new_pts(1,i); y = new_pts(2,i);
    d = sqrt((pts(1,:) - x).^2 + (pts(2,:) - y).^2);
    [Y,I] = sort(d);
    I = I(1:2);
    v1 = [x - pts(1, I(1)) , y - pts(2, I(1))];
    v2 = [pts(1, I(2)) - pts(1, I(1)), pts(2, I(2)) - pts(2, I(1))];
    theta = acos(dot(v1, v2)/(norm(v1)*norm(v2)));
    c1 = cos(theta)*norm(v1);
    c2 = norm(v2) - c1;
    k = c1/c2;
    v3 = (v2/norm(v2))*c1;
    v3 =[ pts(1, I(1)) pts(1, I(1))+v3(1)]; %, [pts(2, I(1)) pts(2, I(1))+v3(2)];
    handles.dat.k = k;
    handles.dat.neighbours = I;
    v1 = [x - pts(1, I(2)) , y - pts(2, I(2))];
    v1 = [v1, 0]';
    v2 =[v2, 0]';
    c = cross(v1, v2);
    handles.dat.theta =-1*sign(c(3))*theta;
    pts = [pts, [x; y]];
   
    
   
n = handles.dat.neighbours;
theta = handles.dat.theta;
k = handles.dat.k;
for i=1:length(pointModels)
    p = pointModels(i).pts;
    V1 = [p(1, n(2)) - p(1, n(1)), p(2, n(2)) - p(2, n(1))];
    v1 = norm(V1);
    V1 = V1/v1;
    v1 = V1*(v1 - (v1/(k+1)));
    R = rotmat(theta);
    V2 = (R*V1')';
    o = tan(theta)*(norm(v1));
    v2 = sqrt(o^2 + (norm(v1))^2)*V2;
    new_p = [p(1, n(1))+v2(1); p(2, n(1))+v2(2)];
    p = [p, new_p];
    pointModels(i).pts = p;
end
end
handles.PointModels = pointModels;


%handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
% for f = 1:length(PointModels)
%    PointModels(f).pts = [PointModels(f).pts, new_pts];
% end
% handles.PointModels = PointModels;
handles.dat.toSave = 1;
handles.dat.changedPointModels = 1;
return;

%%%%%%%%%%%%%%%%%%%%%%
%
% ImportFromPM
%
%%%%%%%%%%%%%%%%%%%%%%
function handles = ImportMeanPM(handles)
pmt=handles.PointModelTemplate;
templatename=get(pmt,'name');
name=templatename(1:findstr(templatename,'.temp_dat')-1);
pathfile=fullfile('Cropped','*.jpg');
pathfileU=fullfile('Cropped','*.JPG');
d=[dir(pathfile),dir(pathfile)];
imagename=d(1).name;
img2=imread(fullfile('Cropped',imagename));
imsiz=size(img2);
pmfile=fullfile('PointModels',name,[imagename(1:findstr(imagename,'.jpg')-1),'_pm.mat']);
temp=load(pmfile,'-mat');
pathfile=fullfile('StatisticalModels',name,'Set_1','ImageList_1','mod_sfam.mat');
sfam=load(pathfile);
sfam=sfam.sfam;
img=double(reshape(sfam.Am,[sfam.siz(2),sfam.siz(1),sfam.siz(3)]));

model=sfam.pdm.Xm; 

M2 = calctrm(temp.pts, model(:), ones(length(temp.pts)/2, 1));
        model2=applytrm(model(:), M2);
        %statistics.n_vertices=length(model2(:));
        %statistics.dist_pts=sqrt(sum((model2(:)-pts(:)).^2))/statistics.n_vertices;
        picture_rmodel=reshape(model2',2,length(model)/2)';
        % ensure the image fills the full range of intensities
        img2=double(img2); % imported image
        %img2=img2-min(min(min(img2))); %*****
        %img2=255*img2/max(max(max(img2)));%*****
        img=double(img); % mean or reference image
        %img=img-min(min(min(img)));%*****
        %img=255*img/max(max(max(img)));%*****
        % Find the pixels that will be warped
        timg=triwarp(100*ones(size(img2(:,:,1))),sfam.ompts,picture_rmodel);
        [rows2,cols2,planes2]=size(img2);
        timg=imerode(timg,strel('disk',7)); %shrink the area a little to prevent black margins *****
        ind=find(timg>1);
        [ii,jj]=ind2sub(size(timg),ind); %correct indexes but ind is wrong size
        % now warp the mean image (appearance) to right size
        picture_img=triwarp(img,sfam.ompts,picture_rmodel); % upsample to zero offset
        % and insert the pixels that have been warped into the display
        [prows,pcols,pplanes]=size(picture_img);
        temp=zeros(size(img2)); % placing the model in the same size image
        temp(1:min(rows2,prows),1:min(cols2,pcols),:)=picture_img(1:min(rows2,prows),1:min(cols2,pcols),:);
        ind=find(ii>rows2);
        ii(ind)=rows2;
        ind=find(jj>cols2);
        jj(ind)=cols2;
        % find the indexes for the correct indexes
        indtemp=sub2ind(size(temp),ii,jj);
        % now reshape so as to use the indexes in ind
        rtemp=reshape(temp,rows2*cols2,planes2);
        rimg2=reshape(img2,rows2*cols2,planes2);
        rimg2(indtemp,:)=rtemp(indtemp,:);
        picture_wimg=reshape(rimg2,[rows2,cols2,planes2]);
        
% but the image and pts are too small, they need to be upsampled to the
% standard size, i.e. load a cropped image
    %I=imread(fullfile(pathname,filename));
    %I=get(handles.PointModelTemplate, 'image');
    model2 = reshape(model2, 2, length(model2)/2);
    ind=find(model2(1,:)<1);
    if ~isempty(ind), model2(1,ind)=1;end
    ind=find(model2(2,:)<1);
    if ~isempty(ind), model2(2,ind)=1;end
    ind=find(model2(1,:)>size(picture_wimg,2));
    if ~isempty(ind), model2(1,ind)=size(picture_wimg,2);end
    ind=find(model2(2,:)>size(picture_wimg,1));
    if ~isempty(ind), model2(2,ind)=size(picture_wimg,1);end
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', model2);
    picture_wimg=picture_wimg/255;
    handles.PointModelTemplate=set(handles.PointModelTemplate, 'image',picture_wimg);
    handles.PointModelTemplate=set(handles.PointModelTemplate, 'imageName','Original Mean');
    handles.PointModelTemplate=set(handles.PointModelTemplate, 'imageDir','');    
    handles.imagesize=size(picture_wimg);
    cla
    imagesc(double(picture_wimg), 'HitTest', 'off'); axis image ij;
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
%     handles.workingDir = pathname;
%     set(handles.imageDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'imageDir')));
%     set(handles.imageNameTxt, 'String', get(handles.PointModelTemplate, 'imageName'));
%     set(handles.templateDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'direc')));
%     set(handles.templateNameTxt, 'String', get(handles.PointModelTemplate, 'name'));


function [handles] = ImportFromPM(handles)
pmt=handles.PointModelTemplate;
templatename=get(pmt,'name');
name=templatename(1:findstr(templatename,'.temp_dat')-1);
pathfile=fullfile('PointModels',name,'*_pm.mat');
[filename, pathname] = uigetfile(pathfile, 'Pick a Point Model file, _pm');
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
    return;
else
    disp(['User selected ', fullfile(pathname, filename)])
    pts = load([pathname, filename]);
    pts = pts.pts;
    pts = reshape(pts, 2, length(pts)/2);
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
    %handles = GlobalInsert(handles);
    imfilename=filename(1:findstr(filename,'_pm')-1);
    imfilename=[imfilename,'.jpg'];
    impathname=pathname(1:findstr(pathname,'PointModels')-1);
    impathname=fullfile(impathname,'Cropped');
    handles = LoadReplacementImage(handles,imfilename,impathname);
    %handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  LoadPointModels
%
%%%%%%%%%%%%%%%%%%%%%%
function [PointModels] = LoadPointModels(PMT)
% Check to see if the point model directory for this template exists, if so
% then load the point models, otherwise, there is no need to update
% anything.
[pmtpath, pmtname, ext, vers] = fileparts(get(PMT, 'name'));
PointModels = [];
if exist(['PointModels', filesep, pmtname], 'dir')
   pmfiles = dir(['PointModels', filesep, pmtname, filesep, '*_pm.mat']);
   pmfiles = {pmfiles.name};
   for f = 1:length(pmfiles)
      pts = load(['PointModels', filesep, pmtname, filesep, pmfiles{f}]);
      pts = pts.pts;
      pts = reshape(pts, 2, length(pts)/2);
      PointModels(f).name = ['PointModels', filesep, pmtname, filesep, pmfiles{f}];
      PointModels(f).pts = pts;
   end
end
return

%%%%%%%%%%%%%%%%%%%%%%
%
%  TurnOffAll
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TurnOffAll(handles)
zoom off; pan off;
set(handles.figMain, 'Pointer', 'Arrow');
set([handles.addremoveBtn, handles.zoomChk, handles.panChk], 'value', 0);
%%%%%%%%%%%%%%%%%%%%%%
%
%  Select Template Image
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SelectTemplateImage(handles)
[filename, pathname] = uigetfile({'*.JPG;*.jpg', 'JPEG Files (*.JPG, *.jpg)'}, 'Select the Template Image', ['Cropped', filesep]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    I = imread([pathname, filesep, filename]);
    if any(size(I)>1024)
        uiwait(warndlg(sprintf('Your template image is larger than the limit 1024x1024\nPlease use the Image processing tool before continuing.\nAny image larger 1024x1024 cannot be processed.')));
        return;
    end
    size(I)
    [p, n] = fileparts(pathname(1:length(pathname)-1));
    if strcmp(n, 'Cropped')
        handles.dat.currentLoopNumber = 0;
        handles.dat.currentLoop = [];
        handles.PointModelTemplate = PointModelTemplate;

        handles.PointModelTemplate = set(handles.PointModelTemplate, 'image', I);
        cla;
        imagesc(get(handles.PointModelTemplate, 'image'), 'HitTest', 'off'); axis image ij;
        handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
        handles.PointModelTemplate = set(handles.PointModelTemplate, 'imageName', filename);
        handles.PointModelTemplate = set(handles.PointModelTemplate, 'imageDir', 'Cropped');
        handles.dat.newTemplate = 1;
        set(handles.imageDirTxt, 'String', 'Cropped');
        set(handles.imageNameTxt, 'String', filename);
    else
        warndlg('Please select a valid image from the ''Cropped'' directory', 'Invalid file selection');
    end
end


%%%%%%%%%%%%%%%%%%%%%%
%
%  NewLoop
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = AddPoint(handles)
handles = TurnOffAll(handles);
switch (get(handles.addPointBtn, 'value'))
    case 0
   %     set(handles.insertPointBtn, 'String', 'New Loop')
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
      %  set(handles.insertPointBtn, 'String', 'Finish Loop')
        set(handles.figMain, 'Pointer', 'crosshair');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Insert Points');
        % First initialise button click function
        %handles.dat.currentLoopNumber = length(get(handles.PointModelTemplate, 'loops')) + 1;
        %handles.dat.currentLoop = [];
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' InsertPoint']);
        %handles.PointModelTemplate = set(handles.PointModelTemplate, 'closedloops', [get(handles.PointModelTemplate, 'closedloops'), 0]);
end
%%%%%%%%%%%%%%%%%%%%%%
%
% InsertPoint
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = InsertPoint(handles)
loops = get(handles.PointModelTemplate, 'loops');
pts = get(handles.PointModelTemplate, 'pts');
primaries = get(handles.PointModelTemplate, 'primaries');
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
CurrentPoint = CurrentPoint(1, 1:2)';

% Here we have to do some calculations to figure out where to place the
% point in the rest of the images....ahhhhhh
x = CurrentPoint(1); y = CurrentPoint(2);
templatename = get(handles.PointModelTemplate, 'name');
[temp_path, templatename, ext, vers] = fileparts(templatename);
if (handles.dat.newTemplate == 0) & (size(pts,2)>1) & CheckForPointModels(templatename)
    d = sqrt((pts(1,:) - x).^2 + (pts(2,:) - y).^2);
    [Y,I] = sort(d);
    I = I(1:2);
    v1 = [x - pts(1, I(1)) , y - pts(2, I(1))];
    v2 = [pts(1, I(2)) - pts(1, I(1)), pts(2, I(2)) - pts(2, I(1))]
    theta = acos(dot(v1, v2)/(norm(v1)*norm(v2)));
    c1 = cos(theta)*norm(v1);
    c2 = norm(v2) - c1;
    k = c1/c2;
    v3 = (v2/norm(v2))*c1;
    v3 =[ pts(1, I(1)) pts(1, I(1))+v3(1)]; %, [pts(2, I(1)) pts(2, I(1))+v3(2)];
    handles.dat.k = k;
    handles.dat.neighbours = I;
    v1 = [x - pts(1, I(2)) , y - pts(2, I(2))];
    v1 = [v1, 0]';
    v2 =[v2, 0]';
    c = cross(v1, v2);
    handles.dat.theta =-1*sign(c(3))*theta;
    pts = [pts, CurrentPoint];
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
    handles = GlobalInsert(handles);
else
    pts = [pts, CurrentPoint];
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);

end
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
%%%%%%%%%%%%%%%%%%%%%%
%
%   Global Insert
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GlobalInsert(handles)
template = handles.PointModelTemplate;
templatename = get(template, 'name');
[templatepath, templatename, ext, vers] = fileparts(templatename);
n = handles.dat.neighbours;
theta = handles.dat.theta;
k = handles.dat.k;
pointModels = handles.PointModels;
for i=1:length(pointModels)
    p = pointModels(i).pts;
    V1 = [p(1, n(2)) - p(1, n(1)), p(2, n(2)) - p(2, n(1))];
    v1 = norm(V1);
    V1 = V1/v1;
    v1 = V1*(v1 - (v1/(k+1)));
    R = rotmat(theta);
    V2 = (R*V1')';
    o = tan(theta)*(norm(v1));
    v2 = sqrt(o^2 + (norm(v1))^2)*V2;
    new_p = [p(1, n(1))+v2(1); p(2, n(1))+v2(2)];
    p = [p, new_p];
    pointModels(i).pts = p;
end
handles.PointModels = pointModels;
return
%%%%%%%%%%%%%%%%%%%%%%
%
%  Add Remove Edge
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = AddRemoveEdge(handles)
zoom off; pan off;
set([handles.zoomChk, handles.panChk, handles.movePointBtn, handles.addPointBtn,...
    handles.delPointBtn, handles.definePrimariesBtn, handles.smoothlandmarksBtn], 'value', 0);

switch (get(handles.addremoveBtn, 'value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
        %    handles = SmoothLandmarks(handles);
    case 1
        set(handles.figMain, 'Pointer', 'crosshair');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Add/Remove Edges');
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' SelectEdge']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  SelectEdge
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SelectEdge(handles)
pts = get(handles.PointModelTemplate, 'pts');
p = get(handles.mainAxes, 'CurrentPoint');
p = p(1,1:2);
distances = sqrt((pts(1,:) - p(1,1)).^2+ (pts(2,:) - p(1,2)).^2);
[v, p1] = min(distances);
ph = zeros(2, 1);
ph(1) = plot(pts(1,p1), pts(2,p1), 'ks', 'MarkerSize', 10, 'HitTest', 'off');
[x, y] = ginput(1);
p = [x, y];
distances = sqrt((pts(1,:) - p(1,1)).^2+ (pts(2,:) - p(1,2)).^2);
[v, p2] = min(distances);
ph(2) = plot(pts(1,p2), pts(2,p2), 'ks', 'MarkerSize', 10, 'HitTest', 'off');
loops = get(handles.PointModelTemplate, 'loops');
if length(loops)>0
    edges = loops{1};
    if size(edges,2)>2
        edges =[];
    end
    if ~isempty(edges)
        edge_ind = [intersect(find(edges(:,1) == p1), find(edges(:,2)== p2)),...
            intersect(find(edges(:,1) == p2), find(edges(:,2)== p1))];

        if ~isempty(edge_ind) % remove the edge
            edges(edge_ind,:) = []; % element in edges disappears
        else % HERE WE SHOULD ONLY ADD THE EDGE IF IT IS LEGAL
             % i.e. secondaries can only appear twice in edges
             % and there should be a warning if they have less than 2
             % entries
            edges = [edges; p1 p2]; % element in edges added to end
        end
    else
        edges = [p1 p2]; % start a new edges matrix
    end
    %loops{1} = edges; % update the edges
else
    edges = [p1 p2];
    %loops{1} = edges;

end
% check that there are no illegal edges, 
ii=[];
jj=1:size(pts,2);
for i=1:size(edges,1)
    %e.g. point connected to itself
    if edges(i,1)==edges(i,2)
        ii(end+1)=i;
    end
    %e.g. nonexistant point
    a=intersect(edges(i,:),jj);
    if isempty(a)
        ii(end+1)=i;
    end
end
edges(ii,:)=[];
loops{1} = edges;
handles.PointModelTemplate = set(handles.PointModelTemplate, 'loops', loops);
delete(ph);
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);

%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = DeletePoints(handles)
handles = TurnOffAll(handles);
set([handles.movePointBtn, handles.definePrimariesBtn], 'Value', 0)
switch (get(handles.delPointBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        set(handles.figMain, 'Pointer', 'cross');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Delete Landmark Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' DeletePoint']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = DeletePoint(handles)
handles.dat.toDelete = [];
pts = get(handles.PointModelTemplate, 'pts');
if size(pts, 2)==0
    return;
end
loops = get(handles.PointModelTemplate, 'loops');
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
delPoint = find(distances == min(distances));
if length(delPoint)<1
    return;
end
    delPoint = delPoint(1);
    handles.dat.toDelete = delPoint;
    pts(:, delPoint) = [];
    % We need to update the loops structure
    if length(loops)>0
        edges = loops{1};
        ind = unique([find(edges(:,1)== delPoint); find(edges(:,2)==delPoint)]);
        edges(ind, :) = [];
        ind = find(edges>= delPoint);
        edges(ind) = edges(ind)-1;
        loops{1} = edges;
    end
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'loops', loops);

    % The lables must be updated also
    labels = get(handles.PointModelTemplate, 'labels');
    if ~isempty(labels)
     ind = find([labels.position]>delPoint);
     for i=ind
         labels(i).position =  labels(i).position-1;
     end
     ind = find([labels.position]==delPoint);
     labels(ind) = [];
     handles.PointModelTemplate = set(handles.PointModelTemplate, 'labels',labels);
    end
    
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
    % And finally the primaries must be altered.
    pris = get(handles.PointModelTemplate, 'primaries');
    pri_exist = find( pris == delPoint);
    if length(pri_exist)>0
        pris(pri_exist) = [];
    end
    pri_exist = find( pris > delPoint);
    if length(pri_exist)>0
        pris(pri_exist) = pris(pri_exist)-1;
    end
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'primaries', pris);
    if handles.dat.newTemplate == 0
        handles = GlobalDelete(handles);
    end
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
    
%%%%%%%%%%%%%%%%%%%%%%
%
%   Global Delete
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GlobalDelete(handles)
template = handles.PointModelTemplate;
templatename = get(template, 'name');
[templatepath, templatename, ext, vers] = fileparts(templatename);
d = handles.dat.toDelete;
if isempty(d)
    return;
end
pointModels = handles.PointModels;
for i=1:length(pointModels)
    p = pointModels(i).pts;
    p(:, d) = [];
    pointModels(i).pts = p;
end
handles.PointModels = pointModels;
return
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = DefinePrimaries(handles)
%  [handles] = DefinePrimaries(handles);
handles = TurnOffAll(handles);

set(handles.movePointBtn, 'Value', 0)
switch(get(handles.definePrimariesBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        set(handles.figMain, 'Pointer', 'Fleur');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Select Primaries Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' TogglePrimary']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TogglePrimary(handles)
pts = get(handles.PointModelTemplate, 'pts');
if size(pts, 2) == 0
    return;
end
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
PrimaryToToggle = find(distances == min(distances));
PrimaryToToggle = PrimaryToToggle(1);
pris = get(handles.PointModelTemplate, 'primaries');
pri_exist = find( pris == PrimaryToToggle);
if length(pri_exist)>0
    pris(pri_exist) = [];
else
    pris = [pris, PrimaryToToggle];
end
handles.PointModelTemplate = set(handles.PointModelTemplate, 'primaries', pris);
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%

function [handles] = MoveMode(handles)
handles = TurnOffAll(handles);

set(handles.definePrimariesBtn, 'value', 0);
switch(get(handles.movePointBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        zoom off; pan off;
        set(handles.figMain, 'Pointer', 'Fleur');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Move Landmark Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' PointSelect'], 'KeyPressFcn', [mfilename, ' MovePointKeyPress']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = PointSelect(handles)
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
ce_pts = get(handles.PointModelTemplate, 'pts');
% Find distance of each point from the selected point on the screen.
distances = sqrt((ce_pts(1,:) - CurrentPoint(1,1)).^2 + (ce_pts(2,:) - CurrentPoint(1,2)).^2);
handles.dat.PointToMove = find(distances == min(distances));
set(handles.figMain, 'WindowButtonMotionFcn', 	[mfilename, ' MovePoint'], 'WindowButtonUpFcn', [mfilename, ' DropPoint']);
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MovePoint(handles)
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
ce_pts = get(handles.PointModelTemplate, 'pts');
ce_pts(1,handles.dat.PointToMove) = CurrentPoint(1,1);
ce_pts(2,handles.dat.PointToMove) = CurrentPoint(1,2);
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', ce_pts);
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleZoom(handles);
set([handles.movePointBtn, handles.addPointBtn, handles.delPointBtn, handles.definePrimariesBtn, handles.smoothlandmarksBtn], 'value', 0);

switch(get(handles.zoomChk, 'Value'))
    case 0
        zoom off;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Zoom is off');
    case 1
        zoom on;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Zoom is on');
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown value for zoom mode');
end

%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TogglePan(handles)
set([handles.movePointBtn, handles.addPointBtn, handles.delPointBtn, handles.definePrimariesBtn, handles.smoothlandmarksBtn], 'value', 0);
switch(get(handles.panChk, 'Value'))
    case 0
        pan off;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Pan is off');
    case 1
        pan on;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Pan is on');
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown value for pan mode');
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  PlotTemplate(A, template)
%
%%%%%%%%%%%%%%%%%%%%%%
function [plotH] = PlotTemplate(A, template, handles, plotH)

if(any(plotH))
    if ishandle(plotH)
        delete(plotH);
    end
    plotH = [];
end
cmenu = uicontextmenu;
I = get(template, 'image');
pts = get(template, 'pts');
pri = get(template, 'primaries');
loops = get(template, 'loops');
closedloops = get(template, 'closedloops');
if isempty(closedloops)
    closedloops = 0;
end
axes(A); hold(A, 'on');

if get(handles.linesChk, 'value')
    
    if length(loops)==1
        edges = loops{1};
        for e = 1:size(edges,1)

            plotH(length(plotH)+1) = plot([pts(1, edges(e,1)),pts(1, edges(e,2))], [pts(2, edges(e,1)),pts(2, edges(e,2))], '-r', 'LineWidth', 1.5, 'MarkerEdgeColor', [112/255 91/255 223/255], 'HitTest', 'off');
        end
    end
%     for i=1:length(loops)
%         looppts = pts(:, loops{i});
%         if (closedloops(i)==1)
%             looppts = [looppts, looppts(:, 1)];
%         end
%         if (size(looppts,2)>0)
%             plotH(length(plotH)+1) = plot(looppts(1, :), looppts(2,:), 'r', 'LineWidth', 1.5, 'MarkerEdgeColor', [112/255 91/255 223/255], 'HitTest', 'off');
%         end
%     end
%     if (handles.dat.currentLoopNumber > 0)
%         looppts = pts(:, loops{handles.dat.currentLoopNumber});
% 
%         if (closedloops(handles.dat.currentLoopNumber)==1)
%             looppts = [looppts, looppts(:, 1)];
%         end
%         if (size(looppts, 2)>0)
%             plotH(length(plotH)+1) = plot(looppts(1,:), looppts(2,:), 'y',  'LineWidth', 1.5, 'HitTest', 'off');
%         end
%     end
end
if get(handles.landmarksChk, 'value')
    if (size(pts, 2) > 0)
        plotH(length(plotH)+1) = plot(pts(1, :), pts(2,:), 'o', 'MarkerEdgeColor', 'y', 'MarkerFaceColor', 'r', 'MarkerSize', 6, 'HitTest', 'on', 'Clipping', 'on', 'UIContextMenu', cmenu);

    end

    if (length(pri)>0)
        plotH(length(plotH)+1) = plot(pts(1, pri), pts(2,pri), 'o', 'MarkerEdgeColor', 'y', 'MarkerFaceColor', 'g', 'MarkerSize', 6, 'HitTest', 'off');
    end
end

if get(handles.labelsChk, 'value')
    for i=1:size(pts, 2)
        plotH(length(plotH)+1) = text(pts(1, i)+2, pts(2,i), num2str(i), 'Color', 'w', 'HitTest', 'off', 'Parent', A, 'Clipping', 'on');
    end
    labels = get(template, 'labels');
    for l = 1:length(labels)
       v = labels(l).position;
       name = labels(l).name;
       if length(name)>0
        plotH(length(plotH)+1) = text(pts(1, v)-2, pts(2,v)+2, name, 'Color', 'w', 'HitTest', 'off', 'Parent', A, 'Clipping', 'on');
       end
   end
end
%axis(A, 'image');
cb1 = ['disp(''Name'');'];
item1 = uimenu(cmenu, 'Label', 'Label', 'Callback', [mfilename, ' addLabel']);
return;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Want to add a label to this point
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = addLabel(handles)
pts = get(handles.PointModelTemplate, 'pts');
labels = get(handles.PointModelTemplate, 'labels');
p = get(handles.mainAxes, 'CurrentPoint');
p = p(1,1:2);
distances = sqrt((pts(1,:) - p(1,1)).^2+ (pts(2,:) - p(1,2)).^2);
[v, p1] = min(distances);
prompt={'Enter the label:'};
name='Label';
numlines=1;
defaultanswer={'New Label'};
newLabel=inputdlg(prompt,name,numlines,defaultanswer);
if isempty(newLabel)
    return;
end
if length(labels)==0
    labels(1).position = p1;
    labels(1).name = newLabel{1};
else
    if any([labels.position]== p1)==0
        labels(end+1).position = p1;
        labels(end).name = newLabel{1};
    else
        p = find([labels.position]== p1);
        labels(p).name = newLabel{1};
    end
end
handles.PointModelTemplate = set(handles.PointModelTemplate, 'labels', labels);
%%%%%%%%%%%%%%%%%%%%%%
%
%  cut_string   //splits directory names so you can see the beginning and
%                   //the end
%%%%%%%%%%%%%%%%%%%%%%
function [s] = cut_string(s)
if (length(s)>50)
    s = [s(1:20), '...', s(end-20:end)];
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  LoadReplacementImage 
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = LoadReplacementImage(handles,filename,pathname)
if nargin<3
    [filename, pathname] = uigetfile('*.jpg', 'Choose an image to load.', ['Cropped', filesep]);
end
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    I=imread(fullfile(pathname,filename));
    %I=get(handles.PointModelTemplate, 'image');
    handles.PointModelTemplate=set(handles.PointModelTemplate, 'image',I);
    handles.PointModelTemplate=set(handles.PointModelTemplate, 'imageName',filename);
    handles.PointModelTemplate=set(handles.PointModelTemplate, 'imageDir',pathname);    
    handles.imagesize=size(I);
    imagesc(I, 'HitTest', 'off'); axis image ij;
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
    handles.workingDir = pathname;
    set(handles.imageDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'imageDir')));
    set(handles.imageNameTxt, 'String', get(handles.PointModelTemplate, 'imageName'));
    set(handles.templateDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'direc')));
    set(handles.templateNameTxt, 'String', get(handles.PointModelTemplate, 'name'));
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Load Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = LoadTemplate(handles)
[filename, pathname] = uigetfile('*.temp_dat', 'Choose a template file to load.', ['Templates', filesep]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    template = load([pathname, filename], '-mat');
    if isfield(template,'PMTemplate')
        handles.PointModelTemplate = template.PMTemplate;
    elseif isfield(template,'model') % legacy models
        pmt=PointModelTemplate;
        pmt=set(pmt,'pts',template.model.pts);
        pmt=set(pmt,'primaries',template.model.pri);
        pmt=set(pmt,'loops',template.model.loop);
        handles.PointModelTemplate = pmt;
    end
    handles.PointModels = LoadPointModels(handles.PointModelTemplate);

    handles.dat.plotH = [];
    set(handles.mainAxes, 'Visible', 'off');
    cla(handles.mainAxes);
    I=get(handles.PointModelTemplate, 'image');
    handles.imagesize=size(I);
    imagesc(I, 'HitTest', 'off'); axis image ij;
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
    handles.workingDir = pathname;
    set(handles.imageDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'imageDir')));
    set(handles.imageNameTxt, 'String', get(handles.PointModelTemplate, 'imageName'));
    set(handles.templateDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'direc')));
    set(handles.templateNameTxt, 'String', get(handles.PointModelTemplate, 'name'));
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Check For Point Models
%
%%%%%%%%%%%%%%%%%%%%%%
function [point_models_exist] = CheckForPointModels(templatename)
point_models_exist = 0;
if ~exist('PointModels', 'dir')
    fprintf('Not in a valid Project directory, ''PointModels'' cannot be found\n');
    point_models_exist = 1;
    return;
end
point_model_dirs = dir('PointModels');
point_model_dirs = {point_model_dirs.name};
for d = 1:length(point_model_dirs)
   if strcmp(templatename, point_model_dirs(d))
    point_models_exist = 1;
   end
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Update Point Models
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdatePointModels(handles)
pmt = handles.PointModelTemplate;
pts = get(pmt, 'pts');
pts = pts(:);
templatename = get(pmt, 'name');
[templatepath, templatename, ext, vers] = fileparts(templatename);

for f = 1:length(handles.PointModels)
    pts = handles.PointModels(f).pts;
    
    ind=find(pts(1,:)<1);
    pts(1,ind)=1;
    ind=find(pts(2,:)<1);
    pts(2,ind)=1;
    ind=find(pts(1,:)>handles.imagesize(2));
    pts(1,ind)=handles.imagesize(2);
    ind=find(pts(2,:)>handles.imagesize(1));
    pts(1,ind)=handles.imagesize(1);

    pts = pts(:);
    [pmpath, pmname, ext, vers] = fileparts(handles.PointModels(f).name);
    %save(['PointModels', filesep, templatename, filesep,pmname, '.mat' ], 'pts')
end
return
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SaveTemplate(handles)
old_template_name = get(handles.PointModelTemplate, 'name');
[path, old_template_name, ext, vers] = fileparts(old_template_name);
[filename, pathname] = uiputfile('*.temp_dat', 'Save Template As...', ['Templates', filesep]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    [p, n] = fileparts(pathname(1:length(pathname)-1));
    if strcmp(n, 'Templates')
        if (handles.dat.changedPointModels == 1)
            [path, templatename, ext, vers] = fileparts(filename);
            while CheckForPointModels(templatename)
                [filename, pathname] = uiputfile('*.temp_dat', 'Save Template As...', ['Templates', filesep]);
                if isequal(filename,0) | isequal(pathname,0)
                    disp('User pressed cancel')
                    return;
                else
                    [path, templatename, ext, vers] = fileparts(filename);
                end
            end
        end
        handles.PointModelTemplate = set(handles.PointModelTemplate, 'name', filename);
        handles.PointModelTemplate = set(handles.PointModelTemplate, 'direc', n);
        PMTemplate = handles.PointModelTemplate;
        save([pathname, filename], 'PMTemplate');
        handles.dat.toSave = 0;
        disp(['User selected ', fullfile(pathname, filename)]);
        handles.workingDir = pathname;
        set(handles.templateDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'direc')));
        set(handles.templateNameTxt, 'String', filename);
        if (handles.dat.changedPointModels == 1) & (handles.dat.newTemplate == 0)
            if ~exist(['PointModels', filesep, templatename])
                mkdir(['PointModels', filesep, templatename]);
            end
            if (handles.dat.changedPointModels == 1) & (handles.dat.newTemplate == 0)
                [handles] = UpdatePointModels(handles);
                % force any fixed points (e.g. border points) to their
                % correct place and create a file specifying sets that form
                % edit series (i.e. that can be turned on and off during
                % point placement)
                templatename=get(handles.PointModelTemplate,'name');
                templatename=templatename(1:findstr(templatename,'.temp_dat')-1);
                fixed_points_file=sprintf('%s_place_fixed_points',templatename);
                set(handles.figMain, 'Pointer', 'watch');
                if exist(fixed_points_file)==2
                    eval(fixed_points_file); % edit_sets
                end
                set(handles.figMain, 'Pointer', 'Arrow');
                handles.dat.changedPointModels = 0;
            end
        end
        handles.dat.newTemplate = 0;
    else
        warndlg('Please save the template in the ''Templates'' directory', 'Invalid file selection');
    end
end
disp('Saving');
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  SmoothLandmarks    //Smooths the secondary landmarks in a given loop
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SmoothLandmarks(handles)
handles = TurnOffAll(handles);
pri = get(handles.PointModelTemplate, 'primaries')';
pts = get(handles.PointModelTemplate, 'pts')';
if isempty(pri)
    return;
end
pts_orig = pts;
currentLoop = handles.dat.currentLoopNumber;
loops = get(handles.PointModelTemplate, 'loops');
edges=loops{1};
%ind = loops{currentLoop};
ind = 1:size(pts_orig,1);
pts = pts(ind,:);
pri = intersect(pri, ind);
for p = 1:length(pri)
    pri(p) = find(ind == pri(p));
end
[pts]=general_smoothlandmarks(pts,pri,edges);
pts_orig(ind, :) = pts;
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts_orig');
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
