function ModelBuilder(arg,option)
    % builds the point models (statistical models are build using ModelGeneratorTool)
global AAMShapemodel_figure_handle
global AAMModelGenerator_handle
global AAMModelBuilder_handle
global AAMSetPicker_handle
global UpdateModel_handle
global PMTemplateBuilder_handle
global PDMWalk_handle
global ShapeSpaceTool_handle

if nargin<2
    option=[];
end
if strcmp(class(arg), 'AAM')
    % Open the GUI for display
    fig = openfig(mfilename, 'reuse');
    movegui(fig, 'center');
    %set(fig,'windowstyle','modal','resize','on')
    Data.handles = guihandles(fig);
        set(fig, 'Color', get(Data.handles.uipanel7, 'BackgroundColor'));
    set(fig, 'Visible', 'on');
    Data.handles = SetGUILevel(Data.handles, getGUILevelInfo);

    Data.handles.figMain = fig;
    AAMModelBuilder_handle=fig;
    
    Data.handles.AAM = arg;
    Data.handles.AAM = UpdateAAMFromDisk(Data.handles.AAM);
    Data.handles.dat.plotH = [];
    Data.handles.dat.targetplotH = [];
    Data.handles.dat.startangle = 0;
    Data.handles.dat.xstartscale = 1;
    Data.handles.dat.ystartscale = 1;
    Data.handles.dat.pointsToMove = [];
    Data.handles.dat.viewSettings  = [1 1 1];
    Data.handles.dat.currentLoopNumber = 0;
    Data.handles.dat.currentElement = AAM_Element;
    Data.handles.dat.currentIndex =1;
    Data.handles.dat.currentLoop = [];
    modelDirec=get(Data.handles.AAM,'modelDirec');
    modelFilename=fullfile(modelDirec,'mod_sfam.mat');
    if exist(modelFilename)==2
        temp=load(fullfile(modelDirec,'mod_sfam.mat'),'-mat');
        sfam=temp.sfam;
        if isfield(sfam,'critical_triangle_expansion')
            Data.handles.dat.critical_triangle_expansion=sfam.critical_triangle_expansion;
        else
            Data.handles.dat.critical_triangle_expansion=10;
        end
    else
            Data.handles.dat.critical_triangle_expansion=10;
    end
    set(Data.handles.TriangleThresholdDefault,'String',sprintf('Triangle default %3.1f',Data.handles.dat.critical_triangle_expansion));
    set(Data.handles.TriangleSetThreshold,'String',sprintf('%3.1f',Data.handles.dat.critical_triangle_expansion));
    Data.handles.workingDir = pwd;
    Data.handles.red=0;
    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    pmt=get(Data.handles.AAM, 'PointModelTemplate');
    pts=get(pmt,'pts');
    Data.handles.dat.indices = 1:size(pts,2); %get(Data.handles.AAM, 'pointindices');
    edit_set_name=get(pmt,'name');
    edit_set_name=[edit_set_name(1:findstr(edit_set_name,'.temp_dat')-1),'.edit_sets'];
    if exist(fullfile('Templates',edit_set_name))==2
        temp=load(fullfile('Templates',edit_set_name),'-mat');
        Data.handles.dat.edit_sets=temp.edit_sets;
    else
        Data.handles.dat.edit_sets=[];
    end
    templatename = get(get(Data.handles.AAM, 'PointModelTemplate'), 'name');
    templatename = templatename(1:length(templatename)-9);
    editset_name=fullfile('Templates',[templatename,'.edit_sets']);
    if exist(editset_name)==2
        temp=load(editset_name,'-mat');
        e_sets=temp.edit_sets;
        for i=1:length(e_sets)
            Data.handles.edit_set(i)=uimenu(Data.handles.EditSets,...
                'Label',e_sets{i}.label,...
                'Checked','on',...
                'Callback',sprintf('ModelBuilder(''edit_sets'',%d);',i));
        end
        i=length(e_sets)+1;
        Data.handles.edit_set(i)=uimenu(Data.handles.EditSets,...
                'Label','Check all',...
                'Checked','on',...
                'Separator','on',...
                'Callback',sprintf('ModelBuilder(''edit_sets'',%d);',-1));
        i=length(e_sets)+2;
        Data.handles.edit_set(i)=uimenu(Data.handles.EditSets,...
                'Label','Un-check all',...
                'Checked','on',...
                'Callback',sprintf('ModelBuilder(''edit_sets'',%d);',-2));
        i=length(e_sets)+3;
        Data.handles.edit_set(i)=uimenu(Data.handles.EditSets,...
                'Label','Separate stacked points',...
                'Checked','off',...
                'Separator','on',...
                'Callback',sprintf('ModelBuilder(''edit_sets'',%d);',-3));
        Data.handles.dat.edit_sets=e_sets;
    else
        Data.handles.dat.edit_sets={};
    end
    Data.handles.dat.separate_points=0;
    templatename=get(pmt,'name');
    templatename=templatename(1:findstr(templatename,'.temp_dat')-1);
    d=dir(fullfile('PointModels',templatename,'*_pm.mat'));
    if isempty(d)
        d=dir(fullfile('Cropped','*.jpg'));
        if isempty(d)
            error('Please copy some images into directory: Cropped');
        else
            first_image_name=d(1).name;
            tempstr=upper(first_image_name);
            first_image_name=first_image_name(1:findstr(tempstr,'.JPG')-1);
            filename=fullfile('PointModels',templatename,[first_image_name,'_pm.mat']);
            save(filename, 'pts','-mat');
        end
    end

%%%% Removed A.I.H.
%     Data.fixed_points_file=sprintf('%s_place_fixed_points',templatename);
%     set(Data.handles.figMain, 'Pointer', 'watch');
%     if exist(Data.fixed_points_file)==2
%         % but only apply if the Templates\*.edit_sets file does
%         % not exist
%         if ~exist(fullfile('Templates',[templatename,'.edit_sets']))
%             eval(Data.fixed_points_file); % edit_sets
%         end
%     else
%         set(Data.handles.FixedPoints,'Visible','off');
%     end
%     set(Data.handles.figMain, 'Pointer', 'Arrow');
%     Data.handles=edit_sets(Data.handles,option);
    
    Data.handles.dat.edit_indices = [];
    Data.handles = SetupModel(Data.handles);
    guidata(fig, Data);
    if exist('AAMShapemodel_figure_handle')
        if ishandle(AAMShapemodel_figure_handle)
            set(AAMShapemodel_figure_handle,'visible','off');
        end
    end
    %uiwait(Data.handles.figMain);
    %     Data = guidata(Data.handles.figMain);
    %     delete(Data.handles.figMain);
    %     return;
else
    %Data = guidata(gcbo);
    Data = guidata(AAMModelBuilder_handle);
    switch arg
        case 'ViewTriangles'
            [Data.handles] = SaveModel(Data.handles);
            Data=ViewTriangles(Data);
        case 'help'
            uiwait(msgbox(['Tips: when moving points,',...
                'use right button to translate all points at once',...
                'press both buttons and slide left-right to rotate ',...
                'and up-down to scale all points at once.'],'Help','help'));
        case 'Refresh'
            aam = load([get(Data.handles.AAM, 'modelDirec'), filesep, get(Data.handles.AAM, 'modelName')], '-mat');
            Data = guidata(Data.handles.figMain);
            pmt=get(Data.handles.AAM,'PointModelTemplate');
            pts=get(pmt,'pts');
            Data.handles.AAM = aam.aam;
            Data.handles.dat.indices = 1:size(pts,2);%get(Data.handles.AAM, 'pointindices');
            Data.handles = SetupModel(Data.handles);
%         case 'FixedPoints'
%             Data.handles = SaveModel(Data.handles);
%             pmt=get(Data.handles.AAM,'PointModelTemplate');
%             templatename=get(pmt,'name');
%             templatename=templatename(1:findstr(templatename,'.temp_dat')-1);
%             index=get(Data.handles.filenameList, 'value');
%             image_names=get(Data.handles.filenameList, 'String');
%             imagename1=image_names{index};
%             imagename=imagename1(1:end-4);
%             Data.fixed_points_file=sprintf('%s_place_fixed_points',templatename);
%             if exist(Data.fixed_points_file)==2
%                 str=sprintf('%s(''%s_pm.mat'');',Data.fixed_points_file,imagename);
%                 eval(str); % edit_sets
%             end
%             Data.handles=clear_plot_handles(Data.handles);
%             Data.handles = SetupModel(Data.handles);
        case 'edit_sets'
            Data.handles = SaveModel(Data.handles);
            Data.handles=edit_sets(Data.handles,option);
            Data.handles = SetupModel(Data.handles);
        case 'FinishedMoving'
            Data.handles.dat.viewSettings
            set(Data.handles.landmarksChk, 'value', Data.handles.dat.viewSettings(1));
            set(Data.handles.labelingChk, 'value', Data.handles.dat.viewSettings(1));
            set(Data.handles.linesChk, 'value', Data.handles.dat.viewSettings(1));
        case 'PullinOutliers' % ensure no point is outside the image
            Data = PullinOutliers(Data);
            [Data.handles] = SaveModel(Data.handles);
        case 'UpdateModel'
            Data.handles = AutoSave(Data.handles, get(Data.handles.AAM, 'modelDirec'), [get(Data.handles.AAM, 'modelName')]);
            UpdateModel(Data.handles.AAM,Data.handles.dat.indices);
        case'SelectPointsToMove'
            [Data.handles] = SelectPointsToMove(Data.handles);
        case'UnselectAll'
            Data.handles = TurnOffAll(Data.handles);
            currentelement = get_element(Data.handles.AAM, get(Data.handles.filenameList, 'value'));
            Data.handles.dat.pointsToMove = [];
            Data.handles.dat.targetplotH = PlotModel(Data.handles.targetAxes, currentelement, Data.handles, Data.handles.dat.targetplotH);
        case 'KeyPressed'
            disp('key was pressed');
        case'SelectAll'
            Data.handles = TurnOffAll(Data.handles);
            currentelement = get_element(Data.handles.AAM, get(Data.handles.filenameList, 'value'));
            Data.handles.dat.pointsToMove = 1:size(get(currentelement, 'pts'), 2);
            if ~isempty(Data.handles.dat.indices)
                Data.handles.dat.pointsToMove = intersect(Data.handles.dat.pointsToMove, Data.handles.dat.indices);
            else
                Data.handles.dat.pointsToMove = Data.handles.dat.pointsToMove;
            end
            Data.handles.dat.targetplotH = PlotModel(Data.handles.targetAxes, currentelement, Data.handles, Data.handles.dat.targetplotH);
        case 'ToggleTemplate'
            if strcmp(get(Data.handles.showTemplateChk, 'Checked'), 'on')
                set(Data.handles.showTemplateChk, 'Checked', 'off');
            else
                set(Data.handles.showTemplateChk, 'Checked', 'on');
            end
            [Data.handles] = UpdateTarget(Data.handles);
            disp('Toggling the tempalte');
        case 'Red'
            [Data.handles] = Red(Data.handles);
        case 'ToggleLabeling'
            [Data.handles] = ToggleLabeling(Data.handles);
        case 'SmoothLandmarks'
             [Data.handles] = SmoothLandmarks(Data.handles);
        case 'ToggleLandmarks'
            [Data.handles] = ToggleLandmarks(Data.handles);
        case 'ToggleLines'
            [Data.handles] = ToggleLines(Data.handles);
        case 'SaveCurrentElement'
            s = get(Data.handles.filenameList, 'String');
            s{get(Data.handles.filenameList, 'value')}
        case 'SelectTemplate'
            [Data.handles] = SelectTemplate(Data.handles);
        case 'TranslatePDM'
            Data.handles = AlignZoom(Data.handles);
            [Data.handles] = TranslatePDM(Data.handles);
        case 'StartPoint'
            [Data.handles] = StartPoint(Data.handles);
        case 'DropPDM'
            set(Data.handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
            Data.handles.dat.startPoint = [];
        case 'ResetPoints'
            Data.handles = AlignZoom(Data.handles);
            Data.handles = ResetPoints(Data.handles);
        case 'RotatePDM'
            Data.handles = AlignZoom(Data.handles);
            Data.handles = RotatePDM(Data.handles);
        case 'ScalePDMX'
            Data.handles = AlignZoom(Data.handles);
            Data.handles = ScalePDMX(Data.handles);
        case 'ScalePDMY'
            Data.handles = AlignZoom(Data.handles);
            Data.handles = ScalePDMY(Data.handles);
        case 'SaveModel'
            [Data.handles] = SaveModel(Data.handles);
        case 'GlobalTransMode'
            Data.handles = AlignZoom(Data.handles);
            [Data.handles] = GlobalTransMode(Data.handles);
        case 'LoadModel'
            [Data.handles] = LoadModel(Data.handles);
            disp('Load a model');
            set([Data.handles.saveModelBtn, Data.handles.selectImageBtn], 'Enable', 'on');
        case 'SelectImageDir'
            [Data.handles] = SelectImageDir(Data.handles);
        case 'Next'
            [Data.handles] = Next(Data.handles);
        case 'Prev'
            [Data.handles] = Prev(Data.handles);
        case 'InsertPoint'
            [Data.handles] = InsertPoint(Data.handles);
        case 'UpdateTemplateLoop'
            [Data.handles] = UpdateTemplateLoop(Data.handles);
        case 'UpdateTargetLoop'
            [Data.handles] = UpdateTargetLoop(Data.handles);
        case 'UpdateTargetAxes'
            [Data.handles] = UpdateTargetAxes(Data.handles);
        case 'MoveMode'
            Data.handles = AlignZoom(Data.handles);
            [Data.handles] = MoveMode(Data.handles);
        case 'PointSelect'
            Data.handles = AlignZoom(Data.handles);
            [Data.handles] = PointSelect(Data.handles);
        case 'MovePoint'
            Data.handles = AlignZoom(Data.handles);
            [Data.handles] = MovePoint(Data.handles);
        case 'DropPoint'
            set(Data.handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
            Data.dat.PointToMove = [];
            set(Data.handles.landmarksChk, 'value', Data.handles.dat.viewSettings(1));
            set(Data.handles.labelingChk, 'value', Data.handles.dat.viewSettings(2));
            set(Data.handles.linesChk, 'value', Data.handles.dat.viewSettings(3));
            currentelement = get_element(Data.handles.AAM, get(Data.handles.filenameList, 'value'));
            Data.handles.dat.targetplotH = PlotModel(Data.handles.targetAxes, currentelement, Data.handles, Data.handles.dat.targetplotH);
        case 'MovePointKeyPress'
            [Data.handles] = MovePointKeyPress(Data.handles);
        case 'ToggleZoom'
            [Data.handles] = ToggleZoom(Data.handles);
        case 'TogglePan'
            [Data.handles] = TogglePan(Data.handles);
        case 'Done'
            if isfield(Data.handles,'Triangles_Fig')
                if ishandle(Data.handles.Triangles_Fig)
                    close(Data.handles.Triangles_Fig);
                end
            end
            Data.handles = SaveModel(Data.handles);
            if exist('AAMShapemodel_figure_handle')
                if ishandle(AAMShapemodel_figure_handle)
                    set(AAMShapemodel_figure_handle,'visible','on');
                end
            end
            % uiresume;
            delete(Data.handles.ModelBuilder);
            AAMToolbox('refresh');
            return;
        otherwise
            error('Unknown Option in AAMToolbox');
    end
%     if isfield(Data.handles, 'figMain')
         guidata(Data.handles.figMain, Data);
%     end
%    DataMain.handles.AAM = Data.handles.AAM;
%    guidata(DataMain.handles.figMain, DataMain);
end


%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Create a temporary figure that shows result of warping to mean 
%
%%%%%%%%%%%%%%%%%%%%%%
function Data=ViewTriangles(Data)
set(Data.handles.figMain, 'Pointer', 'watch');
AAM=Data.handles.AAM;
modelDirec=get(AAM,'modelDirec');
tempDirec=modelDirec(1:findstr(modelDirec,'Set_')-2);
modelfilename=fullfile(tempDirec,'Set_1','ImageList_1','mod_sfam.mat');
critical_triangle_expansion=str2num(get(Data.handles.TriangleSetThreshold,'String'));
if exist(Data.handles.most_recent_PM_filename)
    load(Data.handles.most_recent_PM_filename)
    if exist(modelfilename)
        temp=load(modelfilename);
        sfam=temp.sfam;
        %
        %         pathname=modelfilename(1:findstr(modelfilename,'mod_sfam.mat')-1);
        %         tri_filename=fullfile(pathname,'triangulation.dat');
        %         if exist(tri_filename)==2
        %             t=load(tri_filename,'-mat');
        %             TRI=t.tri;
        %         else
        %             TRI=[];
        %         end
        img=imread(Data.handles.most_recent_image_filename);
        %         if isfield(sfam,'critical_triangle_expansion')
        %             critical_triangle_expansion=sfam.critical_triangle_expansion;
        %         else
        %             critical_triangle_expansion=3;
        %         end
        critical_triangle_expansion=str2num(get(Data.handles.TriangleSetThreshold,'String'));
        indices=1:size(sfam.ompts,1);
        pmt=get(AAM,'PointModelTemplate');
        pmtname=get(pmt,'name');
        pmtfile=fullfile('Templates',pmtname);
            template = load(pmtfile,'-mat'); %['Templates', filesep, template_name, '.temp_dat'], '-mat');
            template = template.PMTemplate;
            loops = get(template, 'loops');
            edges=loops{1};
            [img2,sfimg_safe,img1,tri,allpts,allmeanpts,allTRIoriginals,triangulation_used_for_warp]=warp_to_mean_shape...
                (pts,sfam.ompts,img,indices,critical_triangle_expansion,edges,[sfam.siz(2),sfam.siz(1),sfam.siz(3)]);
            clear gltriwarp % release the warp code space

        if ~isempty(tri)
            if ~isfield(Data.handles,'Triangles_Fig')
                Data.handles.Triangles_Fig=figure;
            else
                if ishandle(Data.handles.Triangles_Fig)
                    figure(Data.handles.Triangles_Fig);
                else
                    Data.handles.Triangles_Fig=figure;
                end
            end
            clf            
            subplot(1,2,2);
            [rows,cols,planes]=size(img1);
            rimg1=reshape(img1,rows*cols,planes);
            NAN=isnan(rimg1(:,1));
            ind=find(NAN);
            rimg1(ind,:)=repmat([128 255 128],size(ind,1),1);
            rrimg1=reshape(rimg1,[rows,cols,planes]);
            imshow(uint8(rrimg1),'InitialMagnification','fit')
            hold on
            xpt=allpts(:,1);%pts(1:2:end);
            ypt=allpts(:,2);%pts(2:2:end);
            triplot(tri,xpt,ypt,'k');
            xp=pts(1:2:end);
            yp=pts(2:2:end);           
            range=1:length(xp);
            indices=intersect(tri(:),range);
            plot(xp(indices),yp(indices),'.r')
            for i=1:length(indices)
                text(xp(indices(i)),yp(indices(i)),sprintf('%d',indices(i)),'color','r');
            end
            triplot(allTRIoriginals,xp,yp,'k');
            triplot(triangulation_used_for_warp,allpts(:,1),allpts(:,2),'w'); %show all the triangles used
            hold off
            subplot(1,2,1);
            [rows,cols,planes]=size(img2);
            rimg2=reshape(img2,rows*cols,planes);
            NAN=isnan(rimg2(:,1));
            ind=find(NAN);
            rimg2(ind,:)=repmat([128 255 128],size(ind,1),1);
            rrimg2=reshape(rimg2,[rows,cols,planes]);
            imshow(uint8(rrimg2),'InitialMagnification','fit')
            hold on
            xpt=allmeanpts(:,1);%pts(1:2:end);
            ypt=allmeanpts(:,2);%pts(2:2:end);
            triplot(tri,xpt,ypt,'k');
            xp=sfam.ompts(:,1);
            yp=sfam.ompts(:,2);           
            plot(xp(indices),yp(indices),'.r')
            for i=1:length(indices)
                text(xp(indices(i)),yp(indices(i)),sprintf('%d',indices(i)),'color','r');
            end
            triplot(allTRIoriginals,sfam.ompts(:,1),sfam.ompts(:,2),'k');
            triplot(triangulation_used_for_warp,allmeanpts(:,1),allmeanpts(:,2),'w');
            hold off
        else
            uiwait(msgbox(sprintf('No triangles expanded by more than %3.1f',critical_triangle_expansion)))
        end
    else
        uiwait(msgbox('Please create an ''Original'' Set_1\ImageList_1 statistical model'))
    end
end
axes(Data.handles.targetAxes);
set(Data.handles.figMain, 'Pointer', 'Arrow');


%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Make visible only those points that are being edited 
%
%%%%%%%%%%%%%%%%%%%%%%
function handles=edit_sets(handles,option)
if nargin<2
    option=0;
end
if option>0
    if strcmpi(get(gcbo,'Checked'),'on')
        set(gcbo,'Checked','off');
    else
        set(gcbo,'Checked','on');
    end
elseif option<0
    if option==-1
        for i=1:length(handles.edit_set)
            set(handles.edit_set(i),'Checked','on');
        end
    elseif option==-2
        for i=1:length(handles.edit_set)
            set(handles.edit_set(i),'Checked','off');
        end
    else
        if strcmpi(get(gcbo,'Checked'),'on')
            set(gcbo,'Checked','off');
            handles.dat.separate_points=0;
        else
            set(gcbo,'Checked','on');
            handles.dat.separate_points=1;
        end
    end
end
edit_sets=handles.dat.edit_sets;
indices=[]; %=Data.handles.dat.indices;
for i=1:length(edit_sets)
    if strcmpi(get(handles.edit_set(i),'Checked'),'on')
        indices=[indices,intersect(handles.dat.indices,edit_sets{i}.indexes)];
        %disp(edit_sets{i}.label);
    end
end
handles.dat.edit_indices=unique(indices);
if length(handles.dat.edit_indices)~=length(handles.dat.edit_indices)
    uiwait(msgbox('incompatibility between edit_indices and indices','Warning','Warning'));
    if any(any(sort(handles.dat.edit_indices)-sort(handles.dat.edit_indices)))
        uiwait(msgbox('edit_indices and indices dissimilar','Warning','Warning'));
    end
end
handles=clear_plot_handles(handles);


function handles=clear_plot_handles(handles);
for i=1:length(handles.dat.plotH)
    plotH=handles.dat.plotH{i};
    if (any(plotH))
        if any(ishandle(plotH))
            delete(plotH);
        end
        plotH = [];
        handles.dat.plotH{i}=plotH;
    end
end
for i=1:length(handles.dat.targetplotH)
    plotH=handles.dat.targetplotH{i};
    if (any(plotH))
        if any(ishandle(plotH))
            delete(plotH);
        end
        plotH = [];
        handles.dat.targetplotH{i}=plotH;
    end
end

% template=get(handles.AAM, 'PointModelTemplate');
% handles.dat.editable_indices=intersect(handles.dat.edit_indices,handles.dat.indices);
% pri = get(template, 'primaries');
% handles.dat.editable_pri_indices=intersect(handles.dat.edit_indices,pri);
% handles.dat.editable_pointsToMove=[]; %intersect(handles.dat.edit_indices,handles.dat.pointsToMove);
    
% intersect any point selection with these indices to finally select only
% those that are visible.

%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Ensure that points lie within the image
%
%%%%%%%%%%%%%%%%%%%%%%
function  handles = Red(handles)
value=get(handles.Red,'value');
if value==0
    handles.red=0;
else
    handles.red=1;
end
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);


%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Ensure that points lie within the image
%
%%%%%%%%%%%%%%%%%%%%%%
function  Data = PullinOutliers(Data);
handles=Data.handles;
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
ce_pts = get(currentelement, 'pts');
ind=find(ce_pts(1,:)<1);
ce_pts(1,ind)=1;
ind=find(ce_pts(2,:)<1);
ce_pts(2,ind)=1;
ind=find(ce_pts(1,:)>handles.imagesize(2));
ce_pts(1,ind)=handles.imagesize(2);
ind=find(ce_pts(2,:)>handles.imagesize(1));
ce_pts(2,ind)=handles.imagesize(1);
currentelement = set(currentelement, 'pts', ce_pts);
handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Reset Points
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ResetPoints(handles)
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
currentelement = set(currentelement, 'pts', get(get(handles.AAM, 'PointModelTemplate'), 'pts'));
handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Toggle Template
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleTemplate(handles)
handles.showTemplateChk
if strcmp( get(handles.showTemplateChk, 'Checked'), 'on')
    cla(handles.templateAxes);
    cla(handles.targetAxes);
    set(handles.targetAxes, 'Visible', 'off');
    set(handles.templateAxes, 'Visible', 'off');
    set(handles.targetAxes2, 'Visible', 'on');
    set(handles.showTemplateChk, 'Checked', 'off');
    elements = get(handles.AAM, 'elements');
    ce = elements{handles.dat.currentIndex};

cf = get(ce, 'imagefilename');
cla(handles.targetAxes2);
    I = imread([get(handles.AAM, 'imageDirectory'), filesep, cf]);
    axes(handles.targetAxes2);
    image(I, 'Parent', handles.targetAxes2, 'HitTest', 'off'); hold(handles.targetAxes2, 'on');
     axis(handles.targetAxes2, 'image', 'ij');
    handles.dat.target2plotH = PlotModel(handles.targetAxes2, ce, handles, handles.dat.target2plotH);

else
    cla(handles.targetAxes2);

    set(handles.showTemplateChk, 'Checked', 'on');
    set(handles.targetAxes, 'Visible', 'on');
    set(handles.templateAxes, 'Visible', 'on');
    set(handles.targetAxes2, 'Visible', 'off');
    set(handles.showTemplateChk, 'Checked', 'on');
    handles = UpdateTarget(handles);
        
        
        
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Toggle Landmarks
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleLandmarks(handles)
currentElement = get_element(handles.AAM, get(handles.filenameList, 'value'));
pts = get(currentElement, 'pts');
if size(pts, 2) < size(get(get(handles.AAM, 'PointModelTemplate'), 'pts'),2)
    handles.dat.plotH = PlotSubModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), size(pts, 2)+1,  handles, handles.dat.plotH);
    handles.dat.targetplotH = PlotSubModel(handles.targetAxes, currentElement, size(pts, 2),  handles, handles.dat.targetplotH);
else
    handles.dat.targetplotH = PlotModel(handles.targetAxes, currentElement, handles, handles.dat.targetplotH);
    handles.dat.plotH = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, handles.dat.plotH);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Toggle Lines
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleLines(handles)
currentElement = get_element(handles.AAM, get(handles.filenameList, 'value'));
pts = get(currentElement, 'pts');
if size(pts, 2) < size(get(get(handles.AAM, 'PointModelTemplate'), 'pts'),2)
    handles.dat.plotH = PlotSubModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), size(pts, 2)+1,  handles, handles.dat.plotH);
    handles.dat.targetplotH = PlotSubModel(handles.targetAxes, currentElement, size(pts, 2),  handles, handles.dat.targetplotH);
else
    handles.dat.targetplotH = PlotModel(handles.targetAxes, currentElement, handles, handles.dat.targetplotH);
    handles.dat.plotH = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, handles.dat.plotH);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Toggle Labels
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleLabeling(handles)
currentElement = get_element(handles.AAM, get(handles.filenameList, 'value'));
pts = get(currentElement, 'pts');
if size(pts, 2) < size(get(get(handles.AAM, 'PointModelTemplate'), 'pts'),2)
    handles.dat.plotH = PlotSubModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), size(pts, 2)+1,  handles, handles.dat.plotH);
    handles.dat.targetplotH = PlotSubModel(handles.targetAxes, currentElement, size(pts, 2),  handles, handles.dat.targetplotH);
else
    handles.dat.targetplotH = PlotModel(handles.targetAxes, currentElement, handles, handles.dat.targetplotH);
    handles.dat.plotH = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, handles.dat.plotH);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Select Image Directory
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SelectImageDir(handles)
directoryname = ['Cropped'];
%directoryname = uigetdir(handles.workingDir);
if directoryname ~= 0
    handles.workingDir = directoryname;
    handles.AAM = set(handles.AAM, 'imageDirectory', directoryname);
    set(handles.imagesDirTxt, 'String', cut_string(get(handles.AAM, 'imageDirectory')));
    files = dir([directoryname, filesep,'*.jpg']);
    filenames = {files.name};
    handles.AAM = set(handles.AAM, 'imageFilenames', filenames);
    % elements = cell(1, length(filenames));
    for f = 1:length(filenames)
        temp = AAM_Element;
        % Comment out, we don't want to store the image in the
        % template, might put in  a 300x300 thumbnail.
        thumbnail = imresize(imread([directoryname, filesep, filenames{f}]), [100 100]);
        temp = set(temp, 'image', thumbnail);
        temp = set(temp, 'imagefilename', filenames{f});
        handles.AAM = add_element(handles.AAM, temp);
    end
    %handles.AAM = set(handles.AAM, 'elements', elements);
    set(handles.filenameList, 'String', get(handles.AAM, 'imageFilenames'));
    axes(handles.targetAxes);
    imagefilenames = get(handles.AAM, 'imageFilenames');
    if length(imagefilenames)>0
        I = imread([get(handles.AAM, 'imageDirectory'), filesep,  imagefilenames{1}]);
        imagesc(I, 'HitTest', 'off'); axis image ij; set(gca, 'XTick', [], 'YTick', []);
        set([handles.targetAxes], 'Visible', 'on');
        set([handles.filenameList, handles.prevBtn, handles.nextBtn], 'Visible', 'on');
        %set([handles.addPointBtn, handles.movePointBtn], 'Enable', 'on');
        %handles = SetupModel(handles);
    end
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Next
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Next(handles)
%zoom out;
%handles = TurnOffAll(handles);
handles = AutoSave(handles, get(handles.AAM, 'modelDirec'), [get(handles.AAM, 'modelName')]);
N = length(get(handles.AAM, 'elements'));
v = get(handles.filenameList, 'value');
if (v < N)
    v = v +1;
    handles.dat.currentIndex =   handles.dat.currentIndex + 1;
else
    v = N;
end
set(handles.filenameList, 'value', v);
set(handles.rotateSlider, 'value', 0);
set(handles.xscaleSlider, 'value', 1);
set(handles.yscaleSlider, 'value', 1);
handles.dat.startangle = 0;
handles.dat.xstartscale = 1;
handles.dat.ystartscale = 1;
handles = UpdateTarget(handles);
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Previous
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Prev(handles)
%zoom out;
%handles = TurnOffAll(handles);
handles = AutoSave(handles, get(handles.AAM, 'modelDirec'), [get(handles.AAM, 'modelName')]);
v = get(handles.filenameList, 'value');
if (v >1)
    v = v -1;
        handles.dat.currentIndex =   handles.dat.currentIndex - 1;
else
    v = 1;
end
set(handles.filenameList, 'value', v);
set(handles.rotateSlider, 'value', 0);
set(handles.xscaleSlider, 'value', 1);
set(handles.yscaleSlider, 'value', 1);
handles.dat.startangle = 0;
handles.dat.xstartscale = 1;
handles.dat.ystartscale = 1;
handles = UpdateTarget(handles);

%%%%%%%%%%%%%%%%%%%%%%
%
%
%  UpdateTemplateLoop
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdateTemplateLoop(handles)
pts = get(get(handles.AAM, 'PointModelTemplate'), 'pts');
if (size(pts, 2)>0)
    loops = get(get(handles.AAM, 'PointModelTemplate'), 'loops');
    CurrentPoint = get(handles.templateAxes, 'CurrentPoint');
    distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
    nearestPoint = find(distances == min(distances));
    nearestPoint = nearestPoint(1);
    for l = 1:length(loops)
        loop = loops{l};
        ind = find(loop == nearestPoint);
        if ~isempty(ind)
            handles.dat.currentLoopNumber = l;
        end
    end
    handles.dat.plotH = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, handles.dat.plotH);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Update Target Loop
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdateTargetLoop(handles)
if get(handles.zoomBtn, 'value')==0
    pts = get(get(handles.AAM, 'PointModelTemplate'), 'pts');
    if (size(pts, 2) == size( get(get_element(handles.AAM, get(handles.filenameList, 'value')), 'pts'),2))
        pts = get(get_element(handles.AAM, get(handles.filenameList, 'value')), 'pts');
        loops = get(get(handles.AAM, 'PointModelTemplate'), 'loops');
        CurrentPoint = get(handles.targetAxes, 'CurrentPoint');
        distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
        nearestPoint = find(distances == min(distances));
        nearestPoint = nearestPoint(1);
        for l = 1:length(loops)
            loop = loops{l};
            ind = find(loop == nearestPoint);
            if ~isempty(ind)
                handles.dat.currentLoopNumber = l;
            end
        end
        handles.dat.targetplotH = PlotModel(handles.targetAxes, get_element(handles.AAM, get(handles.filenameList, 'value')), handles, handles.dat.targetplotH);
    end
end

%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Scale PDMX
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ScalePDMX(handles)
if isempty(handles.dat.pointsToMove)
    set(handles.rotateSlider, 'value', 0);
    set(handles.xscaleSlider, 'value', 1);
    set(handles.yscaleSlider, 'value', 1);
    return;
end
scale = get(handles.xscaleSlider, 'value');
if scale == 0
    scale = 0.001;
end

currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
ce_pts = get(currentelement, 'pts');
mu = mean(ce_pts(:,handles.dat.pointsToMove), 2);
mu = mu*ones(1, length(handles.dat.pointsToMove));
ce_pts(:,handles.dat.pointsToMove) = ce_pts(:,handles.dat.pointsToMove) - mu;
ce_pts(1,handles.dat.pointsToMove) = ce_pts(1,handles.dat.pointsToMove)/handles.dat.xstartscale;
%ce_pts = ce_pts + ce_pts*(scale - handles.dat.startscale);
ce_pts(1,handles.dat.pointsToMove) = ce_pts(1,handles.dat.pointsToMove)*scale;
ce_pts(:, handles.dat.pointsToMove) = ce_pts(:,handles.dat.pointsToMove) + mu;
currentelement = set(currentelement, 'pts', ce_pts);
handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
handles.dat.xstartscale = scale;
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Scale PDMY
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ScalePDMY(handles)
if isempty(handles.dat.pointsToMove)
    set(handles.rotateSlider, 'value', 0);
    set(handles.xscaleSlider, 'value', 1);
    set(handles.yscaleSlider, 'value', 1);
    return;
end
scale = get(handles.yscaleSlider, 'value');
if scale == 0
    scale = 0.001;
end
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
ce_pts = get(currentelement, 'pts');
mu = mean(ce_pts(:, handles.dat.pointsToMove), 2);
mu = mu*ones(1, length(handles.dat.pointsToMove));
ce_pts(:, handles.dat.pointsToMove) = ce_pts(:, handles.dat.pointsToMove) - mu;
ce_pts(2,handles.dat.pointsToMove) = ce_pts(2,handles.dat.pointsToMove)/handles.dat.ystartscale;
%ce_pts = ce_pts + ce_pts*(scale - handles.dat.startscale);
ce_pts(2,handles.dat.pointsToMove) = ce_pts(2,handles.dat.pointsToMove)*scale;
ce_pts(:, handles.dat.pointsToMove) = ce_pts(:, handles.dat.pointsToMove) + mu;
currentelement = set(currentelement, 'pts', ce_pts);
handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
handles.dat.ystartscale = scale;
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Rotate PDM
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = RotatePDM(handles)
if isempty(handles.dat.pointsToMove)
    set(handles.rotateSlider, 'value', 0);
    set(handles.xscaleSlider, 'value', 1);
    set(handles.yscaleSlider, 'value', 1);
    return;
end
theta = get(handles.rotateSlider, 'value');
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
ce_pts = get(currentelement, 'pts');
R = [cos(theta - handles.dat.startangle) -sin(theta-handles.dat.startangle); sin(theta-handles.dat.startangle) cos(theta-handles.dat.startangle)];
mu = mean(ce_pts(:,handles.dat.pointsToMove), 2);
mu = mu*ones(1, length(handles.dat.pointsToMove));
ce_pts(:,handles.dat.pointsToMove) = R*(ce_pts(:,handles.dat.pointsToMove)-mu);
ce_pts(:,handles.dat.pointsToMove) = ce_pts(:,handles.dat.pointsToMove) + mu;
currentelement = set(currentelement, 'pts', ce_pts);
handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
handles.dat.startangle = theta;
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Global Translation of PDM
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GlobalTransMode(handles)

switch(get(handles.globalTranslateBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        zoom off; pan off;
        set([handles.movePointBtn, handles.zoomBtn, handles.panBtn], 'value', 0);
        set(handles.figMain, 'Pointer', 'Fleur');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Global Translation Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' StartPoint']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Start Point
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = StartPoint(handles)
CurrentPoint = get(handles.targetAxes, 'CurrentPoint');
handles.dat.x1 = CurrentPoint(1,:);
set(handles.figMain, 'WindowButtonMotionFcn', 	[mfilename, ' TranslatePDM'], 'WindowButtonUpFcn', [mfilename, ' DropPDM']);

%%%%%%%%%%%%%%%%%%%%%%
%
%
%  TranslatePDM
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TranslatePDM(handles)

CurrentPoint = get(handles.targetAxes, 'CurrentPoint');
x2 = CurrentPoint(1,:);
delta_d = x2 -  handles.dat.x1;
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
ce_pts = get(currentelement, 'pts');
ce_pts(1,handles.dat.pointsToMove) = ce_pts(1,handles.dat.pointsToMove) + delta_d(1,1);
ce_pts(2,handles.dat.pointsToMove) = ce_pts(2,handles.dat.pointsToMove) + delta_d(1,2);
currentelement = set(currentelement, 'pts', ce_pts);
handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
handles.dat.x1 = x2;
%%%%%%%%%%%%%%%%%%%%%%
%
%  TurnOffAll
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TurnOffAll(handles)
zoom off; pan off;
set(handles.figMain, 'Pointer', 'Arrow');
set([handles.movePointBtn, handles.zoomBtn,handles.panBtn, handles.globalTranslateBtn], 'value', 0);
set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  SelectPointsToMove
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SelectPointsToMove(handles)
handles = TurnOffAll(handles);
axes(handles.targetAxes);

[bw, las_x, las_y] = roipoly;
% 
% linehandle = [];
pts = get(get_element(handles.AAM, get(handles.filenameList, 'value')), 'pts');
% zoom off; pan off;
% set(handles.figMain, 'Pointer', 'cross');
% las_x=[];
% las_y=[];
% c=1;
% while c==1
%     [a,b,c]=ginput(1);
%     las_x=[las_x;a];las_y=[las_y;b];
%     linehandle(length(linehandle)+1) = line(las_x,las_y, 'Color', [1 1 1], 'LineWidth', 2);
% end;
% las_x(length(las_x)+1)=las_x(1);
% las_y(length(las_y)+1)=las_y(1);
% linehandle(length(linehandle)+1) = line(las_x,las_y);
% set(handles.figMain, 'Pointer', 'arrow');
% pause(.2);
% delete(linehandle);
% % pause(.2)

in=inpolygon(pts(1,:),pts(2,:),las_x,las_y);
ev_in=find(in>0);
if ~isempty(handles.dat.indices)
    handles.dat.pointsToMove = intersect(ev_in, handles.dat.indices);
else
    handles.dat.pointsToMove = ev_in;
end
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  MoveMode
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MoveMode(handles)
handles = AlignZoom(handles);
template_size = size(get(get(handles.AAM, 'PointModelTemplate'), 'pts'),2);

switch(get(handles.movePointBtn, 'Value'))
    case 0
        set(handles.landmarksChk, 'value', handles.dat.viewSettings(1));
        set(handles.labelingChk, 'value', handles.dat.viewSettings(2));
        set(handles.linesChk, 'value', handles.dat.viewSettings(3));

        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        zoom off; pan off;

        set([handles.globalTranslateBtn, handles.zoomBtn, handles.panBtn], 'value', 0);
        set(handles.figMain, 'Pointer', 'crosshair');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red','String', sprintf('Left  - Single Point, Right  - All, Left + Right  - Scale and Rotate'));
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' PointSelect'], 'WindowButtonUpFcn', [mfilename, ' FinishedMoving']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Point Select
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = PointSelect(handles)
 handles.dat.viewSettings = [get(handles.landmarksChk, 'value') get(handles.labelingChk, 'value'), get(handles.linesChk, 'value')];

movetype = get(handles.figMain,'SelectionType');

CurrentPoint = get(handles.targetAxes, 'CurrentPoint');
currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
ce_pts = get(currentelement, 'pts');
switch movetype
    case 'normal'
        distances = sqrt((ce_pts(1,:) - CurrentPoint(1,1)).^2 + (ce_pts(2,:) - CurrentPoint(1,2)).^2);
        handles.dat.PointToMove = find(distances == min(distances));
        handles.dat.PointToMove = handles.dat.PointToMove(1);
        if isempty(handles.dat.edit_indices)
            temp_ii=handles.dat.PointToMove;
        else
            temp_ii=intersect(handles.dat.PointToMove,handles.dat.edit_indices);
        end
        if ~isempty(temp_ii)
            if handles.dat.separate_points
                handles.dat.PointToMove=temp_ii(1);
            else
                handles.dat.PointToMove=temp_ii;
            end
        else
            handles.dat.PointToMove=[];
        end
        handles.dat.movementType = 'single';
    case 'alt'
        set([handles.labelingChk, handles.linesChk], 'value', 0);
        handles.dat.PointToMove = [CurrentPoint(1,1) CurrentPoint(1,2)];
        handles.dat.movementType = 'all';
        handles.dat.x1 = CurrentPoint(1,:);
        %handles.dat.pointsToMove = 1:size(ce_pts,2);
    case 'extend'
        handles.dat.PointToMove = [CurrentPoint(1,1) CurrentPoint(1,2)];
        %if isfield(handles.dat, 'edit_indices')
        %    handles.dat.PointToMove=intersect(handles.dat.PointToMove,handles.dat.edit_indices);
        %else
            handles.dat.PointToMove=handles.dat.PointToMove;
        %end
        handles.dat.movementType = 'polar';
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown mouse press type');
        handles.dat.movementType = '';
end

set(handles.figMain, 'WindowButtonMotionFcn', 	[mfilename, ' MovePoint'], 'WindowButtonUpFcn', [mfilename, ' DropPoint']);
%%%%%%%%%%%%%%%%%%%%%%
%
%
% Move Point
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MovePoint(handles)
set(handles.figMain, 'WindowButtonMotionFcn', 	'', 'Interruptible','off','BusyAction','cancel');
switch handles.dat.movementType
    case 'single'
        % Moving the selected point
        CurrentPoint = get(handles.targetAxes, 'CurrentPoint');
        currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));
        ce_pts = get(currentelement, 'pts');
        ce_pts(1,handles.dat.PointToMove) = CurrentPoint(1,1);
        ce_pts(2,handles.dat.PointToMove) = CurrentPoint(1,2);
        currentelement = set(currentelement, 'pts', ce_pts);
        handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
        handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
    case 'all'
        handles = TranslatePDM(handles);
    case 'polar'
        currentelement = get_element(handles.AAM, get(handles.filenameList, 'value'));

        CurrentPoint = get(handles.targetAxes, 'CurrentPoint');
        dx = (handles.dat.PointToMove(1) - CurrentPoint(1,1));
        dy = (handles.dat.PointToMove(2) - CurrentPoint(1,2));

        if(dx > 0)
            scale = 0.99;
        elseif(dx < 0)
            scale = 1.01;
        else
            scale = 1;
        end

        if(dy > 0)
            theta = 0.05;
        elseif(dy < 0)
            theta = -0.05;
        else
            theta = 0;
        end

        handles.dat.PointToMove = [CurrentPoint(1,1) CurrentPoint(1,2)];

        ax = scale * cos(theta);
        ay = scale * sin(theta);
        ce_pts = get(currentelement, 'pts');
        ce_pts_orig = ce_pts;
        ce_pts = ce_pts(:, handles.dat.pointsToMove);
        if length(handles.dat.pointsToMove)>0
        m = mean(ce_pts, 2)*ones(1, size(ce_pts,2));
        ce_pts = ce_pts - m;
        R = [ax -ay; ay ax];

        ce_pts = R*ce_pts + m;
        ce_pts_orig(:,handles.dat.pointsToMove) = ce_pts ;
        ce_pts = ce_pts_orig;
        currentelement = set(currentelement, 'pts', ce_pts);
        handles.AAM = set_element(handles.AAM, currentelement, get(handles.filenameList, 'value'));
        handles.dat.targetplotH = PlotModel(handles.targetAxes, currentelement, handles, handles.dat.targetplotH);
        end
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown mouse press type');
        handles.dat.movementType = '';
end
handles.dat.currentElement = get_element(handles.AAM, get(handles.filenameList, 'value'));
set(handles.figMain, 'WindowButtonMotionFcn', 	[mfilename, ' MovePoint'], 'Interruptible','on','BusyAction','cancel');
%%%%%%%%%%%%%%%%%%%%%%
%
%
% Move Point Key Press
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MovePointKeyPress(handles)
set(handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
% Recall the move point function to enable the gui controls
eval(sprintf('%s MoveMode', mfilename));
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Toggle Zoom
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleZoom(handles)
handles = AlignZoom(handles);
switch(get(handles.zoomBtn, 'Value'))
    case 0
        zoom off;
        set(gcf,'pointer', 'arrow' );
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Zoom is off');
    case 1
        zoom on;
        set([handles.globalTranslateBtn, handles.movePointBtn, handles.panBtn], 'value', 0);
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Zoom is on');
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown value for zoom mode');
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Align Zoom
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = AlignZoom(handles)
xlim = get(handles.targetAxes, 'Xlim');
ylim = get(handles.targetAxes, 'Ylim');
currentelement_size = size(get(get_element(handles.AAM, get(handles.filenameList, 'value')), 'pts'),2);
ce_pts = get(get_element(handles.AAM, get(handles.filenameList, 'value')), 'pts');
ce_pts = ce_pts(:, handles.dat.indices);
if ~isempty(ce_pts)
    template_pts = get(get(handles.AAM, 'PointModelTemplate'), 'pts');
    template_pts = template_pts(:, handles.dat.indices);
    xptsind = intersect(find(ce_pts(1, :) > xlim(1)),  find(ce_pts(1,:)<xlim(2)));
    yptsind = intersect(find(ce_pts(2, :) > ylim(1)),  find(ce_pts(2,:)<ylim(2)));
    ptsind = intersect(xptsind, yptsind);
    xborder = [min(ce_pts(1, ptsind) - xlim(1)), xlim(2) - max(ce_pts(1, ptsind))]-5;
    yborder = [min(ce_pts(2, ptsind) - ylim(1)), ylim(2) - max(ce_pts(2, ptsind))]-5;
    if ~isempty(xborder)
        xlim = [min(template_pts(1,ptsind))-xborder(1); max(template_pts(1,ptsind))+xborder(2)];
        ylim = [min(template_pts(2,ptsind))-yborder(1); max(template_pts(2, ptsind))+yborder(2)];
    else
        xlim = get(handles.targetAxes, 'Xlim');
        ylim = get(handles.targetAxes, 'Ylim');
    end
    xoffset = 0; yoffset = 0;
    set(handles.templateAxes, 'Xlim', xlim, 'YLim', ylim);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Toggle Pan
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TogglePan(handles)
handles = AlignZoom(handles);
switch(get(handles.panBtn, 'Value'))
    case 0
        pan off;

        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Pan is off');
    case 1

        pan on;
        set([handles.globalTranslateBtn, handles.movePointBtn, handles.zoomBtn], 'value', 0);

        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Pan is on');
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown value for pan mode');
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  cut_string   //splits directory names so you can see the beginning and
%                   //the end
%%%%%%%%%%%%%%%%%%%%%%
function [s] = cut_string(s)
if (length(s)>83)
    s = [s(1:40), '...', s(end-40:end)];
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Select Template
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SelectTemplate(handles)
[filename, pathname] = uigetfile({'*.temp_dat', 'PointModelTemplate Files (*.temp_dat)'}, 'Select the Template', [handles.workingDir]);

if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    handles.AAM = AAM;
    handles.dat.plotH = [];
    handles.dat.targetplotH = [];
    handles.dat.currentLoopNumber = 0;
    handles.dat.currentLoop = [];
    cla(handles.templateAxes);
    cla(handles.targetAxes);
    P = load([pathname, filesep, filename], '-mat');
    handles.AAM = set(handles.AAM, 'PointModelTemplate', P.PointModelTemplate);
    imagesc(get(get(handles.AAM, 'PointModelTemplate'), 'image'), 'Parent', handles.templateAxes, 'HitTest', 'off'); axis image ij;set(gca, 'XTick', [], 'YTick', []);
    set(handles.templateDirTxt, 'String', cut_string(get(get(handles.AAM, 'PointModelTemplate'), 'direc')));
    set(handles.templateNameTxt, 'String', cut_string(filename));
    handles.dat.plotH = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, []);
    set([handles.saveModelBtn, handles.selectImageBtn], 'Enable', 'on');
    set([handles.templateAxes], 'Visible', 'on');
    set([handles.targetAxes], 'Visible', 'off');
    % set([handles.addPointBtn, handles.movePointBtn], 'Enable', 'off');
    % set([handles.addPointBtn, handles.movePointBtn], 'value', 0);
    set(handles.modelDirTxt, 'String', '');
    set(handles.modelNameTxt, 'String', '');
    set(handles.imagesDirTxt, 'String', 'Filenames');
    set(handles.figMain, 'Pointer', 'Arrow');
    set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
    set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    set([handles.targetAxes], 'Visible', 'off');
    set([handles.filenameList, handles.prevBtn,handles.nextBtn], 'Visible', 'off');
    handles.workingDir = pathname;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Update Target Axes
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdateTargetAxes(handles)
zoom out;
handles = TurnOffAll(handles);
handles = AutoSave(handles, get(handles.AAM, 'modelDirec'), [get(handles.AAM, 'modelName')]);
handles = UpdateTarget(handles);
handles.dat.currentIndex = get(handles.filenameList, 'value');

return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Update Target
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdateTarget(handles)
template = get(handles.AAM, 'PointModelTemplate');
templatename = get(template, 'name');
[path, templatename, ext, vers] = fileparts(templatename);
cla(handles.templateAxes);
cla(handles.targetAxes);
handles.dat.plotH = [];
handles.dat.targetplotH = [];
axes(handles.templateAxes);
if strcmp(class(template), 'PointModelTemplate')
    imagesc(get(template, 'image'), 'Parent', handles.templateAxes, 'HitTest', 'off');set(handles.templateAxes, 'XTick', [], 'YTick', []);
    axis(handles.templateAxes, 'image', 'ij'); hold(handles.templateAxes, 'on');
else
    I = imread([get(handles.AAM, 'imageDirectory'), filesep,  get(template, 'imagefilename')]);
    imagesc(I, 'HitTest', 'off', 'Parent', handles.targetAxes);set(handles.targetAxes, 'XTick', [], 'YTick', []);
    axis(handles.targetAxes, 'image', 'ij'); hold(handles.targetAxes, 'on');

end
ce = get_element(handles.AAM, get(handles.filenameList, 'value'));
cf = get(ce, 'imagefilename');
[path, cfname, ext, vers] = fileparts(cf);
if exist(['PointModels', filesep, templatename, filesep, cfname, '_pm.mat'])
    pts = load(['PointModels', filesep, templatename, filesep, cfname, '_pm.mat']);
    pts = pts.pts;
    if isempty(pts)
        pts = get(template, 'pts');
    else
        if size(pts,1)~=2
            pts = reshape(pts, 2, length(pts)/2);
        end
    end
else
    if size(get(handles.dat.currentElement, 'pts'), 2)>0
        pts = get(handles.dat.currentElement, 'pts');
    else
        pts = get(template, 'pts');
    end
end
ce = set(ce, 'pts', pts);
handles.AAM = set_element(handles.AAM, ce, get(handles.filenameList, 'value'));

handles.dat.currentElement = ce;
cla(handles.targetAxes);
if (length(get(handles.AAM, 'imageDirectory'))>0)
    I = imread([get(handles.AAM, 'imageDirectory'), filesep, cf]);
    axes(handles.targetAxes);
    image(I, 'Parent', handles.targetAxes, 'HitTest', 'off'); hold(handles.targetAxes, 'on'); axis(handles.targetAxes, 'image');
end
handles.dat.plotH = [];
handles.dat.targetplotH = [];
template_pts = get(template, 'pts');
if (size(pts, 2) < size(template_pts, 2))
    handles.dat.plotH = PlotSubModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), size(pts, 2)+1,  handles, handles.dat.plotH);
    handles.dat.targetplotH = PlotSubModel(handles.targetAxes, ce, size(pts, 2),  handles, handles.dat.targetplotH);
else
    handles.dat.targetplotH = PlotModel(handles.targetAxes, ce, handles, handles.dat.targetplotH);
    handles.dat.plotH = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, handles.dat.plotH);
end
set(handles.rotateSlider, 'value', 0);
set(handles.xscaleSlider, 'value', 1);
set(handles.yscaleSlider, 'value', 1);
set(handles.modelDirTxt, 'String', cut_string([getCurrentAAMProjectName, filesep, get(handles.AAM, 'modelDirec')]));
set(handles.modelNameTxt, 'String', get(handles.AAM, 'modelName'));
set(handles.TemplateNumberPoints,'String',sprintf('%d',size(template_pts,2)));
set(handles.PointModelNumberPoints,'String',sprintf('%d',size(pts,2)));
handles.dat.startangle = 0;
handles.dat.xstartscale = 1;
handles.dat.ystartscale = 1;
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  PlotSubModel(A, template)
%
%%%%%%%%%%%%%%%%%%%%%%
function [plotH] = PlotSubModel(A, template, N, handles, plotH)
if(any(plotH))
    delete(plotH);
    plotH = [];
end
I = get(template, 'image');
pts = get(template, 'pts');
pri = get(template, 'primaries');
loops = get(template, 'loops');
closedloops = get(template, 'closedloops');
if (size(pts,2) > N)
    plotHtemp = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, plotH);
    plotH = [plotH plotHtemp];
end
if isempty(closedloops)
    closedloops = 0;
end
axes(A); hold(A, 'on');
if get(handles.landmarksChk, 'value')
    if (size(pts, 2) > 0)
        plotH(length(plotH)+1) = plot(pts(1, 1:N), pts(2,1:N), '.r', 'MarkerSize', 10, 'HitTest', 'off');
    end
    ind = find(pri > N);
    pri(ind) = [];
    if (length(pri)>0)
        plotH(length(plotH)+1) = plot(pts(1, pri), pts(2,pri), '.g', 'MarkerSize', 10, 'HitTest', 'off');
    end
end
if (N>0)
    plotH(length(plotH)+1) = plot(pts(1, N), pts(2,N), '.w', 'MarkerSize', 10, 'HitTest', 'off');
end
if get(handles.labelingChk, 'value')
    for i=1:N
        plotH(length(plotH)+1) = text(pts(1, i), pts(2,i), num2str(i), 'Color', 'w', 'HitTest', 'off', 'Clipping', 'on');
    end
end
axis(A, 'image');
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  PlotModel(A, template)
%
%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Model    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SaveModel(handles)
%[filename, pathname] = uiputfile('*.model_dat', 'Pick a File', [get(handles.AAM, 'modelDirec'), filesep, get(handles.AAM, 'modelName')]);
%if isequal(filename,0) | isequal(pathname,0)
%    disp('User pressed cancel')
%else
handles = AutoSave(handles, get(handles.AAM, 'modelDirec'), [get(handles.AAM, 'modelName')]);

%handles = AutoSave(handles, pathname, filename);
disp('Saving');
%end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Auto Save
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = AutoSave(handles, pathname, filename)
aam = handles.AAM;
if isempty(get(aam, 'modelName'))
    return;
end
save([get(aam, 'modelDirec'), filesep, get(aam, 'modelName')], 'aam');
disp('Auto Saving');
disp(['User selected ', fullfile(pathname, filename)])
handles.workingDir = pathname;
set(handles.modelDirTxt, 'String', cut_string([getCurrentAAMProjectName, filesep, get(handles.AAM, 'modelDirec')]));
set(handles.modelNameTxt, 'String', get(handles.AAM, 'modelName'));
completedElements = get(handles.AAM, 'completeElements');
completedElements = unique([completedElements, get(handles.filenameList, 'value')]);
handles.AAM = set(handles.AAM, 'completeElements', completedElements);
elements = get(handles.AAM, 'elements');
template = get(handles.AAM, 'PointModelTemplate');
templatename = get(template, 'name');
templatename = templatename(1:length(templatename)-9);
if ~exist(['PointModels', filesep, templatename], 'dir')
    mkdir(['PointModels', filesep, templatename]);
end
ce = elements{handles.dat.currentIndex};
pts = get(ce, 'pts');
pts = pts(:);
name = get(ce, 'imagefilename');
disp(['Saving ', name]);
fullname=['PointModels', filesep, templatename, filesep, name(1:length(name)-4), '_pm.mat'];
save(fullname, 'pts');
handles.most_recent_PM_filename=fullname;
handles.most_recent_image_filename=fullfile('Cropped',name);
%%%%%%%%%%%%%%%%%%%%%%
%
%  Load Model    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = LoadModel(handles)
[filename, pathname] = uigetfile('*.model_dat', 'Pick a File', [handles.workingDir]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    model = load([pathname, filesep, filename], '-mat');
    handles.AAM = model.aam;
    handles.workingDir = pathname;
    handles = SetupModel(handles);
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Setup Model    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles]  = SetupModel(handles)
if isempty(get(get(handles.AAM, 'PointModelTemplate'), 'image'))
    return;
end
handles.dat.plotH ={};
handles.dat.targetplotH ={};
cla(handles.templateAxes);
imagesc(get(get(handles.AAM, 'PointModelTemplate'), 'image'), 'Parent', handles.templateAxes, 'HitTest', 'off'); 
axis(handles.templateAxes, 'image', 'ij');    
set(handles.templateAxes, 'XTick', [], 'YTick', []);
set([handles.templateAxes], 'Visible', 'on');
handles.dat.plotH = PlotModel(handles.templateAxes, get(handles.AAM, 'PointModelTemplate'), handles, handles.dat.plotH);
set(handles.templateDirTxt, 'String', cut_string(get(get(handles.AAM, 'PointModelTemplate'), 'direc')));
set(handles.templateNameTxt, 'String', get(get(handles.AAM, 'PointModelTemplate'), 'name'));
set(handles.modelDirTxt, 'String', cut_string([getCurrentAAMProjectName, filesep, get(handles.AAM, 'modelDirec')]));
set(handles.modelNameTxt, 'String', get(handles.AAM, 'modelName'));
set(handles.imagesDirTxt, 'String', cut_string(get(handles.AAM, 'imageDirectory')));
if (length(get(handles.AAM, 'imageFilenames'))>0)
   % set(handles.filenameList, 'String', cut_string(get(handles.AAM, 'imageFilenames')));
        set(handles.filenameList, 'String', (get(handles.AAM, 'imageFilenames')));

    set([handles.filenameList, handles.prevBtn, handles.nextBtn], 'Visible', 'on');
    filenames = get(handles.AAM, 'imageFilenames');
    I = imread([get(handles.AAM, 'imageDirectory'), filesep, filenames{get(handles.filenameList, 'value')}]);
    cla(handles.targetAxes);
    axes(handles.targetAxes);
    imagesc(I, 'Parent', handles.targetAxes, 'HitTest', 'off'); axis(handles.targetAxes, 'image', 'ij');set(handles.targetAxes, 'XTick', [], 'YTick', []);
    set([handles.targetAxes], 'Visible', 'on');
    handles.imagesize=size(I);
else
    set([handles.filenameList, handles.prevBtn, handles.nextBtn], 'Visible', 'off');
    set([handles.targetAxes], 'Visible', 'off');
end
elements = get(handles.AAM, 'elements');
templatename = get(get(handles.AAM, 'PointModelTemplate'), 'name');
templatename = templatename(1:length(templatename)-9);
templatepoints = get(get(handles.AAM, 'PointModelTemplate'), 'pts');
set(handles.TemplateNumberPoints,'String',sprintf('%d',size(templatepoints,2)));
imagenames = get(handles.AAM, 'imageFilenames');
elements = {};
for e = 1:length(imagenames)
    ce = AAM_Element;
    imagename = imagenames{e};
    elements{e} = ce;
    elements{e} = set( elements{e}, 'imagefilename', imagename);
    elements{e} = set( elements{e}, 'primaries', get(get(handles.AAM, 'PointModelTemplate'), 'primaries'));
    elements{e} = set( elements{e}, 'closedloops', get(get(handles.AAM, 'PointModelTemplate'), 'closedloops'));
    elements{e} = set( elements{e}, 'loops', get(get(handles.AAM, 'PointModelTemplate'), 'loops'));
end
handles.AAM = set(handles.AAM, 'elements', elements);
aam = handles.AAM;
save([get(handles.AAM, 'modelDirec'), filesep, get(handles.AAM, 'modelName')], 'aam');
handles = UpdateTarget(handles);
% add in the edit set menu items

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  SmoothLandmarks    //Smooths the secondary landmarks in a given loop
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SmoothLandmarks(handles)
% if  handles.dat.currentLoopNumber<=0
%         set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Must select a loop to smooth');
%     return;
% end
handles = TurnOffAll(handles);
elements = get(handles.AAM, 'elements');
ce = elements{handles.dat.currentIndex};
loops = get(ce, 'loops')';
edges=loops{1};

pri = get(ce, 'primaries')';
pri = sort(pri);
pts = get(ce, 'pts')';
if isempty(pri)
    return;
end
pts_orig = pts;
currentLoop = handles.dat.currentLoopNumber;
loops = get(ce, 'loops');
ind = 1:size(pts,1);

[pts]=general_smoothlandmarks(pts,pri,edges);

pts_orig(ind, :) = pts;
ce = set(ce, 'pts', pts_orig');
elements{handles.dat.currentIndex} = ce;
handles.AAM = set(handles.AAM, 'elements', elements);
handles.dat.targetplotH = PlotModel(handles.targetAxes, ce, handles, handles.dat.targetplotH);
%%%%%%%%%%%%%%%%%%%%
%
% SetGUILevel
%
%%%%%%%%%%%%%%%%%%%%
function handles = SetGUILevel(handles, level)
if level==1
    set(handles.globalPosPanel, 'Visible', 'off');
    set(handles.trianglePanel, 'Visible', 'off');
    set(handles.EditSets, 'Visible', 'off');
    
    
end