function [value] = GridEditorTool(varargin)
% function [value] = GridEditorTool(varargin)
%
% Notes: every region must have at least 4 control points so we can find an
% inverse transform for the strain matrix.
% Hanna, 2005

if checkSATDir(pwd) == 0
    fprintf('You are not in a valid SectorAnalysisToolbox Project directory\n');
    return;
end
error(nargchk(0,inf,nargin));
% Open, move, and get the handles from the figure file.
fig = openfig(mfilename, 'reuse');
movegui(fig, 'center');
set(fig, 'Visible', 'on');
handles = guihandles(fig);
set(fig, 'Color', get(handles.uipanel10, 'BackgroundColor'));

% Set all the callback functions
set(handles.load_ungrown_shape_btn, 'callback', {@doLoadUngrownShape});

set(handles.zoom_btn, 'callback', {@doZoom});
set(handles.warp_to_shape_btn, 'callback', {@doWarpToShape});
set(handles.pan_btn, 'callback', {@doPan});
set(handles.grid_popup, 'callback', {@doChangeGrid});
set(handles.calc_region_stat_btn, 'callback', {@doCalcRegionStats});
set(handles.edit_edge_btn, 'callback', {@doEditEdgePoints});
set(handles.concavity_check_btn, 'callback', {@doConcavityCheck});
set(handles.save_grid_btn, 'callback', {@doSaveGrid});
set(handles.add_control_point_btn, 'callback', {@doAddCtrlPt});
set(handles.select_regions_btn, 'callback', {@doSelectRegions});
set(handles.move_control_point_btn, 'callback', {@doMoveCtrlPt});
set(handles.build_regions_btn, 'callback', {@doBuildRegions});
set(handles.clear_ctrl_pts_btn, 'callback', {@doClearCtrlPts});
set(handles.del_control_point_btn, 'callback', {@doDelCtrlPt});
set(handles.auto_grid_btn, 'callback', {@doAutoGrid});
set(handles.shape_springs_btn, 'callback', {@doSelectShapeSprings});



% Toggle Callbacks
set(handles.toggle_mean_shape, 'callback', {@doToggleMeanShape});
set(handles.toggle_internal_spring, 'callback', {@doToggleInternalSpring});
set(handles.toggle_external_spring, 'callback', {@doToggleExternalSpring});
set(handles.toggle_centroids, 'callback', {@doToggleCentroids});
set(handles.toggle_grid, 'callback', {@doToggleGrid});
set(handles.new_grid_btn, 'callback', {@doNewGrid});





% Initialize the application data structure
ad.figMain = fig;
ad = init_ad_struct(ad);
ad.handles = handles;

if ~exist(ad.MeanShapeName, 'file')
    fprintf('There is no mean shape to align a grid to, aborting!\n');
    delete(fig)
    return;
else
    ad.mean_shape = load(ad.MeanShapeName);
    ad.mean_shape = ad.mean_shape.mean_shape;
end
ad.regions.shape = fliplr(ad.mean_shape);
setappdata(0,'GridEditorToolData',ad);
show_shape;
doUpdateGridList();
doChangeGrid(ad.handles.grid_popup);

try
    uiwait(fig);
catch
    if ishandle(fig)
        delete(fig)
    end
end
value = 0;
return;
%%%%
%
%
%
%%%%
function ad = init_ad_struct(ad)
ad.StagedDirString = 'Staged';
ad.OriginalsDirString = 'Originals';
ad.ProcessedDirString = 'Processed';
ad.RegionDirName = 'RegionData';
ad.DataDir = [ad.StagedDirString, filesep, 'Data'];
ad.UngrowthDataDir = [ad.DataDir, filesep, 'UngrowthData'];
ad.GridDir = [ad.DataDir, filesep, 'Grids'];
ad.edge_margin = 20;
if ~exist(ad.GridDir, 'dir'); mkdir(ad.GridDir); end;
ad.MeanShapeName = [ad.DataDir, filesep, 'mean_shape.mat'];
ad.layers  = [];
ad.ctrl_pt_to_move = [];
ad.regions = init_regions_struct;
ad.av_info = [];
ad.sector_region_info = [];
ad.region_size_threshold = 0.33;
ad.grid_plot_handle = [];
ad.vertex_plot_handle =[];
ad.mean_shape_plot_handle =[];
ad.edge_plot_handle = [];
ad.spring_marker_handle = [];
ad.spring_line_handle = [];
ad.spring_text_handle = [];
ad.shape_spring_handle = [];
ad.edge_marker_handle = [];
ad.grid_name = [];
ad.edge_line_handle = [];
ad.edge_text_handle = [];
ad.centroid_plot_handle = [];
ad.ctrl_pt_handle =[];
ad.ctrl_pt_handle =[];
ad.projectpath = pwd;
ad.value = 0;
%%%%
%
%
%
%%%%
function show_shape
ad =getappdata(0, 'GridEditorToolData');
I = zeros(ceil(max(ad.mean_shape(:,1)))+ceil(min(ad.mean_shape(:,1))),ceil( max(ad.mean_shape(:,2)))+ceil( min(ad.mean_shape(:,2))));
I = roipoly(I, ad.mean_shape(:,2), ad.mean_shape(:,1));
imagesc(I, 'Parent', ad.handles.imageAxis); hold(ad.handles.imageAxis, 'on');
axis(ad.handles.imageAxis, 'image');
set(ad.figMain, 'Colormap', copper);
setappdata(0, 'GridEditorToolData', ad);
doPlotMeanShape;
return;
%%%%
%
%
%
%%%%
function doToggleMeanShape(toggle_mean_shape, evd)
ad =getappdata(0, 'GridEditorToolData');
if ishandle(ad.mean_shape_plot_handle)
    if get(toggle_mean_shape, 'value')
        set(ad.mean_shape_plot_handle, 'Visible', 'on');
    else
        set(ad.mean_shape_plot_handle, 'Visible', 'off');
    end
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%
%%%%
function doNewGrid(newgridbtn, evd)
ad = getappdata(0, 'GridEditorToolData');
ad = init_ad_struct(ad);
if ~exist(ad.MeanShapeName, 'file')
    fprintf('There is no mean shape to align a grid to, aborting!\n');
    delete(fig)
    return;
else
    ad.mean_shape = load(ad.MeanShapeName);
    ad.mean_shape = ad.mean_shape.mean_shape;
end
ad.regions.shape = fliplr(ad.mean_shape);
setappdata(0,'GridEditorToolData',ad);
show_shape;
return;
%%%%
%
%
%
%%%%
function doToggleGrid(toggle_grid, evd)
ad =getappdata(0, 'GridEditorToolData');
if ishandle(ad.grid_plot_handle)
    if get(toggle_grid, 'value')
        set(ad.grid_plot_handle, 'Visible', 'on');
    else
        set(ad.grid_plot_handle, 'Visible', 'off');
    end
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%
%%%%
function doToggleInternalSpring(toggle_internal, evd)
ad =getappdata(0, 'GridEditorToolData');
if ishandle(ad.spring_marker_handle)
    if get(toggle_internal, 'value')
        set(ad.spring_marker_handle, 'Visible', 'on');
    else
        set(ad.spring_marker_handle, 'Visible', 'off');
    end
end
if ishandle(ad.spring_line_handle)
    if get(toggle_internal, 'value')
        set(ad.spring_line_handle, 'Visible', 'on');
    else
        set(ad.spring_line_handle, 'Visible', 'off');
    end
end
if ishandle(ad.spring_text_handle)
    if get(toggle_internal, 'value')
        set(ad.spring_text_handle, 'Visible', 'on');
    else
        set(ad.spring_text_handle, 'Visible', 'off');
    end
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%
%%%%
function doToggleExternalSpring(toggle_internal, evd)
ad =getappdata(0, 'GridEditorToolData');
if ishandle(ad.edge_marker_handle)
    if get(toggle_internal, 'value')
        set(ad.edge_marker_handle, 'Visible', 'on');
    else
        set(ad.edge_marker_handle, 'Visible', 'off');
    end
end
if ishandle(ad.edge_line_handle)
    if get(toggle_internal, 'value')
        set(ad.edge_line_handle, 'Visible', 'on');
    else
        set(ad.edge_line_handle, 'Visible', 'off');
    end
end
if ishandle(ad.edge_text_handle)
    if get(toggle_internal, 'value')
        set(ad.edge_text_handle, 'Visible', 'on');
    else
        set(ad.edge_text_handle, 'Visible', 'off');
    end
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%
%%%%
function doToggleCentroids(toggle_centroids, evd)
ad =getappdata(0, 'GridEditorToolData');
if ishandle(ad.centroid_plot_handle)
    if get(toggle_centroids, 'value')
        set(ad.centroid_plot_handle, 'Visible', 'on');
    else
        set(ad.centroid_plot_handle, 'Visible', 'off');
    end
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%
%%%%
function doUpdateGridList()
ad =getappdata(0, 'GridEditorToolData');
files = dir([ad.GridDir, filesep, '*.mat']);
files = {files.name};
if length(files)>0
    set(ad.handles.grid_popup, 'String', files);
else
    set(ad.handles.grid_popup, 'String', {'No Grids Found'});
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%%%%
function doCalcRegionStats(region_stats_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
R = ad.regions.R;
centroids = ad.regions.centroids;
str = get(ad.handles.grid_popup, 'String');
val = get(ad.handles.grid_popup, 'value');
if strcmp(str{val}, 'No Grids Found')
    return;
end
StagedDirString = ad.StagedDirString;
FILES = dir(StagedDirString);
if isempty(FILES);
    return;
end;
FILES = {FILES.name};
FILES = cleanup_stage_list(FILES);
[s,v] = listdlg('Name', 'Select Stages To Calc. Region Stats', 'PromptString','Select the stages you wish to calculate regional statistical for:', 'SelectionMode','multiple', 'ListString',FILES, 'ListSize', [300, 200]);
if isempty(s)
    return;
end
pause(.01);
FILES = FILES(s);
waitbar_h = waitbar(0, 'Calculating region statistics, please wait...');
number_of_regions = size(R,3)-1;
av_info = cell(length(FILES), 1);
for i=1:length(FILES)
    stage = [StagedDirString, filesep, FILES{i}];    
    [region_info, areas] = calc_stage_sector_info(stage, R, centroids);
    av_info{i}.average_stage_sector_info = calc_average_stage_sector_info(region_info);
    av_info{i}.stage = stage;
    av_info{i}.mean_area = mean(areas);
    av_info{i}.median_area = median(areas);
    av_info{i}.mode_area = mode(areas);
    waitbar(i/length(FILES), waitbar_h);
end
close(waitbar_h);
ad.av_info = av_info;

%ad.sector_region_info = sector_region_info;
setappdata(0, 'GridEditorToolData', ad);
plotRegionInfo

%%%
%
%
%%%
function plotRegionInfo
ad = getappdata(0, 'GridEditorToolData');
centroids = ad.regions.centroids;
av_info = ad.av_info{length(ad.av_info)}.average_stage_sector_info;
scale = 1;
cla(ad.handles.thumb_axes);
hold(ad.handles.thumb_axes, 'on');
for ii=1:size(av_info,3)
    eh = gtlib_plotGrowthTensor('growth_tensor', av_info(:,:,ii), 'offset', centroids(ii,:), 'Colour', [1 1 1], 'Parent', ad.handles.thumb_axes);
end
hold(ad.handles.thumb_axes, 'off');
display_organ(ad.regions.xy_regions, ad.handles.thumb_axes, [1 1 0], 1);
setappdata(0, 'GridEditorToolData', ad);
%%%
%
%
%%%
function doLoadUngrownShape(load_ungrown_shape_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
[filename, pathname] = uigetfile('*.mat', 'Pick an Ungrowth File', [ad.UngrowthDataDir, filesep]);
if isequal(filename,0) || isequal(pathname,0)
    disp('User pressed cancel')
else
    f = load([pathname, filesep, filename]);
    f = f.ungrown_grid;
    % We need to align and scale the ungrown shape to the mean shape
    templ.marks = double(ad.regions.shape(:,1:2)');
    data.marks = double(f(length(f)).shape(:,1:2)');
    [procdata,theta,templ] = procrustes(data,templ);
    N = length(f);
    S = f(N).S;
    GD = adjust_grid_data(f(N), theta);
    ad.regions.Springs.S = GD.S;
    ad.regions.Springs.Edgs = GD.Edgs;
    ad.regions.Springs.order = GD.order;
    ad.regions.control_pts = GD.control_pts;
    ad.regions.orig_control_pts = GD.control_pts;
    ad.regions.shape = GD.shape;
    ad.regions.REGS = GD.REGS;
    ad.mean_shape = (GD.shape);
    [ad.regions.xy_regions] = Edgs2xy_regions(ad.regions.Springs.Edgs, ad.regions.Springs.order);
end
setappdata(0, 'GridEditorToolData', ad);
cla(ad.handles.imageAxis);
doPlotAll;
return;
%%%
%
%
%%%
function [grid_data] = adjust_grid_data(grid_data, theta)
if nargin<2
    return;
end
grid_data.shape = align_vector(grid_data.shape, theta);
grid_data.S(:,end-1:end) = align_vector(grid_data.S(:,end-1:end), theta);
grid_data.Edgs(:,end-1:end) = align_vector(grid_data.Edgs(:,end-1:end), theta);
grid_data.edge_petal(:,1:2) = align_vector(grid_data.edge_petal(:,1:2), theta);
grid_data.control_pts = align_vector(grid_data.control_pts, theta);
return;
%%%
%
%
%%%
function v = align_vector(v, theta)
p = size(v,1);
v = double(v);
v = transpose(((1/theta.scale)*rotmat(theta.phi)')*(v' - theta.transl*ones(1,p)));
return;
%%%%
%
%
%
%%%%
function doChangeGrid(grid_popup, evd)
ad =getappdata(0, 'GridEditorToolData');
str = get(grid_popup, 'String');
val = get(grid_popup, 'value');
if strcmp(str{val}, 'No Grids Found')
    return;
end
file = [ad.GridDir, filesep, str{val}];
if exist(file, 'file')
    region_info = load(file);
    ad.regions = region_info.region_info;
else
    ad.regions.R = [];
    ad.regions.grid_xy = [];
    ad.regions.vertex = [];
    ad.regions.edge = [];
    ad.regions.edge_petal = [];
    ad.regions.neighbours = [];
end
setappdata(0, 'GridEditorToolData', ad);
doPlotAll;
doToggleAll;
%%%%
%
%
%
%%%%
function doZoom(zoom_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
zoom off;
pan off;
if get(ad.handles.zoom_btn, 'value')
    zoom on;
end
%%%%
%
%
%
%%%%
function doPan(pan_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
zoom off;
pan off;
if get(ad.handles.pan_btn, 'value')
    pan on;
end
%%%%
%
%
%
%%%%
function doConcavityCheck(concavity_check_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
if isempty(ad.regions)
    return;
end
str = get(ad.handles.grid_popup, 'String');
val = get(ad.handles.grid_popup, 'value');
if strcmp(str{val}, 'No Grids Found')
    return;
end
[xyreg, order, value] = ConcavityCheck('Springs', ad.regions.Springs.S, 'Edgs', ad.regions.Springs.Edgs, 'E',ad.regions.Springs.E, 'Order', ad.regions.order, 'Layers', ad.regions.layers); %
ad.regions.xy_regions = xyreg;
ad.regions.order = order;
grid_name = 'Untitled.mat';
setappdata(0, 'GridEditorToolData', ad);
doPlotAll;
%%%%
%
%
%
%%%%
function doWarpToShape(warp2shape_btn, evd)
ad = getappdata(0, 'GridEditorToolData');
[filename, pathname] = uigetfile('*.mat', 'Pick grown grid', [ad.GridDir, filesep]);
if isequal(filename,0) || isequal(pathname,0)
    disp('User pressed cancel');
    return;
else
    grown_grid = load([pathname, filesep, filename]);
    grown_grid = grown_grid.region_info;
end
[filename, pathname] = uigetfile('*.mat', 'Pick grid to warp', [ad.GridDir, filesep]);
if isequal(filename,0) || isequal(pathname,0)
    disp('User pressed cancel');
    return;
else
    new_grid = load([pathname, filesep, filename]);
    new_grid = new_grid.region_info;
end
grown_grid.control_pts = [];
gshape = grown_grid.shape;
nshape = new_grid.shape;
ctrlpts = new_grid.control_pts;
[wpts] = TPS_pts_warp(ctrlpts, nshape, gshape);
grown_grid.control_pts = wpts;
grown_grid = align_edge_vertices2edge(grown_grid, ad.edge_margin);
ad.regions = grown_grid;
setappdata(0, 'GridEditorToolData', ad);
doUpdateGridList;
doPlotAll;
%%%
%
%%%
function [regions] = init_regions_struct
regions.R = [];
regions.layers = [];
%regions.vertex = [];
%regions.edge = [];
regions.control_pts = [];
regions.shape = [];
regions.neighbours = [];
regions.grid_xy = [];
regions.centroids = [];
regions.order = [];
regions.REGS = [];
regions.region_vertices = [];
regions.region_vertices_ind = [];
return;


%%%%
%
%
%
%%%%
function doPlotCentroids()
ad = getappdata(0, 'GridEditorToolData');
cen = ad.regions.centroids;
if ishandle(ad.centroid_plot_handle)
    delete(ad.centroid_plot_handle);
    ad.centroid_plot_handle = [];
end
if ~isempty(cen)
    ad.centroid_plot_handle = plot(ad.handles.imageAxis, cen(:,1), cen(:,2), 'o', 'MarkerEdgeColor', 'y', 'MarkerFaceColor', 'y');
end
setappdata(0, 'GridEditorToolData', ad);
return;

function doPlotShapeSprings()
ad = getappdata(0, 'GridEditorToolData');
if ~isfield(ad.regions, 'Springs')
    return;
end

if ~isfield(ad.regions.Springs, 'shape_springs')
    return;
end
if ishandle(ad.shape_spring_handle)
    delete(ad.shape_spring_handle);
    ad.shape_spring_handle = [];
end
M = size(ad.regions.Springs.S,1);
pts = ad.regions.Springs.Edgs(:, 2*M+1:end);
shpsprings = ad.regions.Springs.shape_springs;
hold(ad.handles.imageAxis, 'on');

%for i=1:length(shpsprings)
%   spr = shpsprings(i);
%   ad.shape_spring_handle(end+1) = plot(ad.handles.imageAxis, [pts(spr.indx(1), 1) pts(spr.indx(2),1)], [pts(spr.indx(1), 2) pts(spr.indx(2),2)], '-', 'Color', 'k');
%end
hold(ad.handles.imageAxis, 'off');

%%%%
%
%
%
%%%%
function doPlotSprings()
ad = getappdata(0, 'GridEditorToolData');
if ~isfield(ad.regions, 'Springs')
    return;
end
Springs = ad.regions.Springs.S;
if ishandle(ad.spring_marker_handle)
    delete(ad.spring_marker_handle);
    ad.spring_marker_handle = [];
end
if ishandle(ad.spring_line_handle)
    delete(ad.spring_line_handle);
    ad.spring_line_handle = [];
end
if ishandle(ad.spring_text_handle)
    delete(ad.spring_text_handle);
    ad.spring_text_handle = [];
end
[ad.spring_marker_handle, ad.spring_line_handle, ad.spring_text_handle] = display_springs(Springs, ad.handles.imageAxis);
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function doPlotEdgeSprings()
ad = getappdata(0, 'GridEditorToolData');
if ~isfield(ad.regions, 'Springs')
    return
end
Springs = ad.regions.Springs.S;
Edgs = ad.regions.Springs.Edgs;
if ishandle(ad.edge_marker_handle)
    delete(ad.edge_marker_handle);
    ad.edge_marker_handle = [];
end
if ishandle(ad.edge_line_handle)
    delete(ad.edge_line_handle);
    ad.edge_line_handle = [];
end
if ishandle(ad.edge_text_handle)
    delete(ad.edge_text_handle);
    ad.edge_text_handle = [];
end
[ad.edge_marker_handle, ad.edge_line_handle, ad.edge_text_handle] = display_edges(Springs, Edgs, ad.handles.imageAxis);
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function doBuildRegions(auto_grid_btn, evd)
ad = getappdata(0, 'GridEditorToolData');

if isempty(ad.regions.region_vertices)
    fprintf('You must select your region vertices first\n');
    return;
end



w_h = waitbar(0, 'Building regions...');
shape = ad.mean_shape(:,1:2);
R = pts2binim(fliplr(ad.regions.shape));
R2(:,:,1) = R;
s = (double(ad.regions.shape));
image_axis = ad.handles.imageAxis;
ad.regions.REGS = {};
%region_vertices = [ad.regions.shape; ad.regions.control_pts];
region_vertices_ind = ad.regions.region_vertices_ind;
region_vertices = ad.regions.region_vertices;
for i=1:length(region_vertices_ind)
    regions_pts = region_vertices(region_vertices_ind{i},:);
    r2 = roipoly(zeros(size(R)), regions_pts(:,1), regions_pts(:,2));
    r2 = r2&R;
    R2 = cat(3, R2, r2);
    mask = imdilate(r2, strel('disk', 10));
    [y, x] = find(bwperim(mask));
    [in, on] = find(inpolygon(round(s(:,1)), round(s(:,2)), x, y));
    ad.regions.REGS{i}.edge = in;
    [in, on] = find(inpolygon(round(ad.regions.control_pts(:,1)), round(ad.regions.control_pts(:,2)), x, y));
    ad.regions.REGS{i}.vertex = in;
    setappdata(0, 'GridEditorToolData', ad);
end
waitbar(1/4, w_h);
show_layers(R2, ad.handles.thumb_axes);
waitbar(2/4, w_h);
control_ind = {};
for i=1:length(ad.regions.REGS)
    control_ind{i} = ad.regions.REGS{i}.vertex;
end
[edge, vertex, REGS] = layers2vertex_edge(R2, double(ad.regions.shape), control_ind, ad.regions.control_pts, 1);
waitbar(3/4, w_h);

edge = sort_all_region_pts(edge);
fprintf('Now finding the neighbours for each region...\n');
N = find_neighbours(R2);
fprintf('done.\n');
grid_xy = calc_grid_outline(R2);
waitbar(4/4, w_h);
centroids = get_centroids(R2);


edge_petal = make_edge_petal(ad.regions);
ad.regions.layers = show_layers(R2);
ad.regions.R = R2;
ad.regions.control_pts = ad.regions.control_pts;
ad.regions.shape = ad.regions.shape;
ad.regions.edge_petal = edge_petal;
ad.regions.neighbours = N;
ad.regions.grid_xy = grid_xy;
ad.regions.centroids = centroids;
ad.regions.xy_regions = edge(2:end);
ad.regions.order = [];
ad.regions.REGS = REGS;
setappdata(0, 'GridEditorToolData', ad);
[ad.regions.Springs.S, ad.regions.Springs.E, ad.regions.Springs.Edgs] = doMakeSprings(R2, edge, N, centroids);
%[ad.regions.Springs.shape_springs] = makeShapeSprings(ad.regions.region_vertices, ad.regions.region_vertices_ind, centroids, ad.regions.Springs.Edgs);
indtoremove = calc_remove_ind(vertex, ad.regions.Springs.Edgs);
ad.regions.Springs.Edgs_All = ad.regions.Springs.Edgs;
ad.regions.Springs.Edgs = ad.regions.Springs.Edgs(indtoremove, :);
ad.regions.order = makeorder(ad.regions.Springs.S, ad.regions.Springs.Edgs);
ad.regions.Springs.edges_removed_ind = setdiff(1:size(ad.regions.Springs.Edgs_All,1), indtoremove);
region_info = ad.regions;
close(w_h);
setappdata(0, 'GridEditorToolData', ad);
doUpdateGridList;
doPlotAll;
fprintf('Leaving Manual Grid Editing Mode.\n');

%%%%
%
%
%
%%%%
function doSelectShapeSprings(btn, evd)
ad = getappdata(0, 'GridEditorToolData');
fprintf('Entering Manual Grid Editing Mode.\n');
shape = ad.mean_shape(:,1:2);
image_axis = ad.handles.imageAxis;
R = pts2binim(shape);
shape = fliplr(shape);
cla(image_axis);
ad.grid.control_pts = ad.regions.control_pts;
ad.grid.shape = shape;
imagesc(R, 'Parent', image_axis); hold(image_axis, 'on');
axis(image_axis, 'image', 'xy');
plot(image_axis, shape(:,1), shape(:,2), 'go');
plot(ad.handles.imageAxis,ad.regions.control_pts(:,1), ad.regions.control_pts(:,2), 's', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
colormap copper;
image_axis = ad.handles.imageAxis;
hold(image_axis, 'on');
pts = [ad.regions.shape; ad.regions.control_pts];
pts = double(pts);
R = pts2binim(ad.regions.shape);
R2(:,:,1) = R;
s = double(ad.regions.shape);
button = 1;
i = 2;
region_vertices = pts;
region_vertices_ind = {};
button = 1;
M = size(ad.regions.Springs.S,1);
centroids = ad.regions.Springs.S(:, 2*M+1:end);

pts = ad.regions.Springs.Edgs(:, 2*M+1:end);
plot(ad.handles.imageAxis,pts(:,1), pts(:,2), 's', 'MarkerFaceColor', 'b', 'MarkerEdgeColor', 'y');


vh = [];
[x, y, button] = ginput(2);
shape_springs = struct([]);
indx = 1;
while ~isempty(button)
    fprintf('Click on the shape springs %d\n', i-1);
    [val, ind1] = min(matdistance(pts, [x(1); y(1)]'));
    vh = cat(1, vh, plot(image_axis, pts(ind1,1), pts(ind1,2), 'o', 'MarkerEdgeColor', 'r', 'MarkerFaceColor', 'r','HitTest', 'off'));
    [val, ind2] = min(matdistance(pts, [x(2); y(2)]'));
    vh = cat(1, vh, plot(image_axis, pts(ind2,1), pts(ind2,2), 'o', 'MarkerEdgeColor', 'r', 'MarkerFaceColor', 'r','HitTest', 'off'));
    p1 = pts(ind1,:);
    p2 = pts(ind2,:);
    plot(ad.handles.imageAxis,[p1(1) p2(1)], [p1(2) p2(2)], ':', 'Color', 'r');
    midpoint = (p1+p2)/2;
    [val, region] = min(matdistance(centroids, [midpoint(1); midpoint(2)]'));
    shape_springs(indx).indx = [ind1 ind2];
    shape_springs(indx).dist = sqrt(sum((p1-p2).^2,2));
    shape_springs(indx).region = region;
    indx = indx + 1;
    [x, y, button] = ginput(2);
end
% ad.regions.region_vertices = region_vertices;
% ad.regions.region_vertices_ind = region_vertices_ind;
ad.regions.Springs.shape_springs = shape_springs;
setappdata(0, 'GridEditorToolData', ad);
return;
%%%
%
%%%
function shape = getmeanshape(ad)
shape = [];
if ~isfield(ad, 'mean_shape')
    fprintf(' - no field ad.mean_shape\n');
end
if isempty(ad.mean_shape)
    return;
end
shape = ad.mean_shape;
return;
%%%
%
%%%
function pts = getctrlpoints(ad)
shape = [];
if ~isfield(ad.regions, 'control_pts')
    fprintf(' - no field ad.regions.control_pts\n');
end
if isempty(ad.regions.control_pts)
    return;
end
pts = ad.regions.control_pts;
return;
%%%
%
%%%
function plotShape(ad)
shape = getmeanshape(ad);
if isempty(shape)
    return;
end
plot(ad.handles.imageAxis, shape(:,2), shape(:,1), 'go');
return
%%%
%
%%%
function plotCtrlPoints(ad)
pts = getctrlpoints(ad);
if isempty(pts)
    return;
end
plot(ad.handles.imageAxis, pts(:,1), pts(:,2), 's', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
return
%%%
%
%%%
function drawOrganImage(ad)
shape = getmeanshape(ad);
if isempty(shape)
    return;
end
image_axis = ad.handles.imageAxis;
R = pts2binim(shape);
imagesc(R, 'Parent', image_axis); hold(image_axis, 'on');

return
%%%%
%
%%%%
function doSelectRegions(select_region_btn, evd)
ad = getappdata(0, 'GridEditorToolData');
fprintf('Entering Manual Grid Editing Mode.\n');

% Draw the organ image, the shape points and the control points
image_axis = ad.handles.imageAxis;
cla(image_axis);
drawOrganImage(ad);
plotShape(ad);
plotCtrlPoints(ad);
axis(image_axis, 'image');
colormap(image_axis, 'copper');
hold(image_axis, 'on');
% end of drawing

ctrl_pts = ad.regions.control_pts;
pts = [ad.regions.shape; ctrl_pts];
pts = double(pts);
region_vertices_ind = {};
region_ctrl_pt_ind = {};
[xi,yi] = getline(image_axis, 'closed'); % Get rect info from the user.
while ~isempty(xi)
    if length(xi)>=3
        in = find(inpolygon(pts(:,1), pts(:,2), xi,yi));
        [rpts, ind] = order_xy_pts(pts(in,:));
        region_vertices_ind = cat(1, region_vertices_ind, in(ind));
        in = find(inpolygon(ctrl_pts(:,1), ctrl_pts(:,2), xi,yi));
        [sctrlpts, ind] = order_xy_pts(ctrl_pts(in,:));
        region_ctrl_pt_ind = cat(1, region_ctrl_pt_ind, in(ind));
        plot(image_axis, rpts(:,1), rpts(:,2), 'o-', 'Color', rand(1,3));
    end
    [xi,yi] = getline(image_axis, 'closed'); % Get rect info from the user.
end
ad.regions.region_vertices = pts;
ad.regions.region_vertices_ind = region_vertices_ind;
ad.regions.region_ctrl_pt_ind = region_ctrl_pt_ind;
setappdata(0, 'GridEditorToolData', ad);
return;

%%%%
%
%
%
%%%%
function [ctrl_pt_handle] = plot_control_pts
ad =getappdata(0, 'GridEditorToolData');
rv = ad.regions.control_pts;
if ~isempty(rv)
    ctrl_pt_handle = plot(ad.handles.imageAxis,rv(:,1), rv(:,2), 's', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
end
colormap copper;
setappdata(0, 'GridEditorToolData', ad);

%%%%
%
%
%
%%%%
function doMoveCtrlPt(move_ctrl_pt_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
if ~isfield(ad.regions, 'region_vertices_ind')
    return;
end
rv = ad.regions.region_vertices_ind;
if isempty(rv)
    set(move_ctrl_pt_btn, 'Value', 0);
    return;
end
switch (get(move_ctrl_pt_btn, 'Value'))
    case 0
        ad.regions = align_edge_vertices2edge(ad.regions, ad.edge_margin);
        set(ad.figMain, 'Pointer', 'Arrow');
        set(ad.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
    case 1
        fprintf('Entering Move Point Mode.\n');
        clear_view;
        ad = getappdata(0, 'GridEditorToolData');
        ad.ctrl_pt_handle = plot_control_pts;
        setappdata(0, 'GridEditorToolData', ad);
        doPlotRegions;

        set(ad.figMain, 'Pointer', 'crosshair');
        set(ad.figMain, 'BackingStore', 'on', 'WindowButtonDownFcn',  {@select_ctrl_pt});
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%
%%%%
function doPlotRegions
ad =getappdata(0, 'GridEditorToolData');
for i=2:length(ad.regions.REGS)
    r = ad.regions.REGS{i}.vertex;
    pts = ad.regions.control_pts(r, :);
    pts = [pts; pts(1,:)];
    pts = order_xy_pts(pts);
    plot(ad.handles.imageAxis, pts(:,1), pts(:,2), '-o', 'MarkerFaceColor', 'g', 'HitTest', 'on');
end
setappdata(0, 'GridEditorToolData', ad);

%%%%
%
%
%
%%%%
function select_ctrl_pt(fig, evd)
ad =getappdata(0, 'GridEditorToolData');
cp = get(ad.handles.imageAxis, 'CurrentPoint');
cp = cp(1,1:2);
%ctrl_pts = [ad.regions.shape; ad.regions.control_pts];
ctrl_pts = [ad.regions.control_pts];
d = sqrt(sum((ctrl_pts - ones(size(ctrl_pts,1),1)*cp).^2,2));
[val, ind] = min(d);
ad.ctrl_pt_to_move = ind(1);
setappdata(0, 'GridEditorToolData', ad);
set(fig, 'WindowButtonMotionFcn', {@move_ctrl_pt}, 'WindowButtonUpFcn',  {@drop_ctrl_pt});
return;
%%%%
%
%
%
%%%%
function move_ctrl_pt(fig, evd)
ad =getappdata(0, 'GridEditorToolData');
if isempty(ad.ctrl_pt_to_move)
    return;
end
cp = get(ad.handles.imageAxis, 'CurrentPoint');
cp = cp(1,1:2);
pt2move = ad.ctrl_pt_to_move;
ad.regions.control_pts(pt2move,:) = cp;

setappdata(0, 'GridEditorToolData', ad);
clear_view;
doPlotRegions;
return;
%%%%
%
%
%
%%%%
function drop_ctrl_pt(fig, evd)
ad =getappdata(0, 'GridEditorToolData');
set(fig, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
ad.ctrl_pt_to_move = [];
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function doDelCtrlPt(del_ctrl_btn, evd)
ad = getappdata(0, 'GridEditorToolData');
switch (get(del_ctrl_btn, 'Value'))
    case 0
        ad.regions = align_edge_vertices2edge(ad.regions, ad.edge_margin);
        set(ad.figMain, 'Pointer', 'Arrow');
        set(ad.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
    case 1
        ad.regions.region_vertices = [];
        fprintf('Entering Delete Control Point Mode.\n');
        clear_view;
        if ~isempty(ad.regions.control_pts)
            plot(ad.handles.imageAxis,ad.regions.control_pts(:,1), ad.regions.control_pts(:,2), 's', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
        end
        colormap copper;
        fprintf('Delete Control Points\n');
        set(ad.figMain, 'Pointer', 'crosshair');
        set(ad.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn',  {@delete_ctrl_pt});
end
setappdata(0, 'GridEditorToolData', ad);
%%%%
%
%
%
%%%%
function delete_ctrl_pt(fig, evd)
ad =getappdata(0, 'GridEditorToolData');
ad.regions.region_vertices = [];
cp = get(ad.handles.imageAxis, 'CurrentPoint');
cp = cp(1,1:2);
ctrl_pts = ad.regions.control_pts;
[val, ind] = min(sqrt(sum((ctrl_pts - ones(size(ctrl_pts,1),1)*cp).^2,2)));
ad.regions.control_pts(ind(1), :) = [];
% We must also update the indices in REGS
for i=2:length(ad.regions.REGS)
    r = ad.regions.REGS{i}.vertex;
    r(r == ind(1)) = [];
    indx = find(r > ind(1));
    r(indx) = r(indx) - 1;
    ad.regions.REGS{i}.vertex = r;
end

setappdata(0, 'GridEditorToolData', ad);
clear_view;
if ~isempty(ad.regions.control_pts)
    plot(ad.handles.imageAxis,ad.regions.control_pts(:,1), ad.regions.control_pts(:,2), 's', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
end
return;
%%%%
%
%
%
%%%%
function doAddCtrlPt(add_ctrl_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
switch (get(add_ctrl_btn, 'Value'))
    case 0
        ad.regions = align_edge_vertices2edge(ad.regions, ad.edge_margin);
        clear_view;
        if ~isempty(ad.regions.control_pts)
            plot(ad.handles.imageAxis,ad.regions.control_pts(:,1), ad.regions.control_pts(:,2), 's', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
        end
        set(ad.figMain, 'Pointer', 'Arrow');
        set(ad.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
    case 1
        fprintf('Entering Manual Control Point Placing Mode.\n');
        clear_view;
        if ~isempty(ad.regions.control_pts)
            plot(ad.handles.imageAxis,ad.regions.control_pts(:,1), ad.regions.control_pts(:,2), 's', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
        end
        colormap copper;
        fprintf('Place Control Points\n');
        set(ad.figMain, 'Pointer', 'crosshair');
        set(ad.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn',  {@place_ctrl_pt});
end
setappdata(0, 'GridEditorToolData', ad);

%%%%
%
%
%
%%%%
function place_ctrl_pt(fig, evd)
ad =getappdata(0, 'GridEditorToolData');
ad.regions.region_vertices = [];
cp = get(ad.handles.imageAxis, 'CurrentPoint');
cp = cp(1,1:2);
fprintf(' - x: %4.2f, y: %4.2f.\n', cp(1), cp(2));
hold(ad.handles.imageAxis, 'on');
plot(ad.handles.imageAxis,cp(1), cp(2), 's-', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'y');
ad.regions.control_pts = [ad.regions.control_pts; cp];
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function clear_view()
ad = getappdata(0, 'GridEditorToolData');
shape = fliplr(ad.regions.shape(:,1:2));
ad.mean_shape = shape;
image_axis = ad.handles.imageAxis;
R = pts2binim(shape);
shape = fliplr(shape);
cla(image_axis);
imagesc(R, 'Parent', image_axis); hold(image_axis, 'on');
axis(image_axis, 'image');
ad.mean_shape_plot_handle = plot(image_axis, shape(:,1), shape(:,2), 'go');
setappdata(0, 'GridEditorToolData', ad);
return
%%%%
%
%
%
%%%%
function doClearCtrlPts(clear_ctrl_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
ad.regions = init_regions_struct;
ad.shape = ad.mean_shape;
image_axis = ad.handles.imageAxis;
shape = ad.mean_shape(:,1:2);
R = pts2binim(shape);
ad.regions.R = R;
shape = fliplr(shape);
ad.regions.shape = shape;
show_shape;
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function doPlotMeanShape
ad = getappdata(0, 'GridEditorToolData');
if ishandle(ad.mean_shape_plot_handle)
    delete(ad.mean_shape_plot_handle);
    ad.mean_shape_plot_handle = [];
end
ad.mean_shape_plot_handle = plot(ad.handles.imageAxis, ad.mean_shape(:,2), ad.mean_shape(:,1), '-o', 'MarkerEdgeColor', 'r', 'MarkerFaceColor', 'y', 'Color', 'b');
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function doPlotGrid
ad = getappdata(0, 'GridEditorToolData');
if ishandle(ad.grid_plot_handle)
    delete(ad.grid_plot_handle);
    ad.grid_plot_handle = [];
end
grid_xy = ad.regions.grid_xy;
if isfield(ad.regions, 'xy_regions')
    ad.grid_plot_handle = display_organ(ad.regions.xy_regions, ad.handles.imageAxis, [0 0 1]);
    hold(ad.handles.imageAxis, 'on');
end
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function doEditEdgePoints(edit_edge_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
str = get(ad.handles.grid_popup, 'String');
val = get(ad.handles.grid_popup, 'value');
if strcmp(str{val}, 'No Grids Found')
    return;
end
Edgs = ad.regions.Springs.Edgs_All;
Spr = ad.regions.Springs.S;
xyreg = ad.regions.xy_regions;
removed_ind = ad.regions.Springs.edges_removed_ind;
[ad.regions.Springs.Edgs, ad.regions.Springs.edges_removed_ind, ad.regions.order, value] = EditEdgePoints('Springs', Spr, 'Edges', Edgs, 'xyregs', xyreg, 'removed_indices', removed_ind, 'order', ad.regions.order, 'Layers', ad.regions.layers);
ad.regions.order = makeorder(ad.regions.Springs.S, ad.regions.Springs.Edgs);
setappdata(0, 'GridEditorToolData', ad);
region_info = ad.regions;
doPlotAll;
return;
%%%%
%
%
%
%%%%
function doAutoGrid(auto_grid_btn, evd)
ad =getappdata(0, 'GridEditorToolData');
reduce = 1;
reg_x = str2double(get(ad.handles.xdim_txt, 'String'));
reg_y = str2double(get(ad.handles.ydim_txt, 'String'));
[R, REGS, E, edge_petal, dx, dy]=auto_regions(reg_x, reg_y, ad.mean_shape);
outline = round(fliplr(ad.mean_shape));
pts = [];
for i=1:length(REGS)
    pts = [pts; REGS{i}];
end
ind = [];
for i=1:size(pts,1)
    d = matdistance(pts(i,:)', pts');
    close_ind = find(d<50);
    close_ind = close_ind(close_ind>i);
    ind = cat(2, ind, close_ind);
end
pts(ind,:) = [];
ad.regions.control_pts = pts;
setappdata(0, 'GridEditorToolData', ad);
return;
%%%%
%
%
%
%%%%
function doSaveGrid(save_grid_btn, evd)
ad = getappdata(0, 'GridEditorToolData');
set(ad.figMain, 'Pointer', 'watch');
region_info = ad.regions;
fprintf('Saving grid data...\n');
grid_name = 'Untitled.mat';
[filename, pathname] = uiputfile(grid_name, 'Pick an Grid Filename', [ad.GridDir, filesep, grid_name]);
if isequal(filename,0) || isequal(pathname,0)
    disp('User pressed cancel')
    set(ad.figMain, 'Pointer', 'arrow');
    return;
else
    disp(['User selected ', fullfile(pathname, filename)])
end
average_region_info = ad.av_info;
save([pathname, filename], 'region_info', 'average_region_info', '-mat');

fprintf('done.\n');
uiwait(msgbox('Finished saving your grid data.','Save Done','modal'));
set(ad.figMain, 'Pointer', 'arrow');
ad.grid_name = [pathname,filesep, filename];
setappdata(0, 'GridEditorToolData', ad);
doUpdateGridList;
return;
%%%
%
%%%
function doToggleAll
ad =getappdata(0, 'GridEditorToolData');
doToggleMeanShape(ad.handles.toggle_mean_shape);
doToggleInternalSpring(ad.handles.toggle_internal_spring);
doToggleExternalSpring(ad.handles.toggle_external_spring);
doToggleCentroids(ad.handles.toggle_centroids);
doToggleGrid(ad.handles.toggle_grid);
axis(ad.handles.imageAxis, 'image');
%%%%
%
%
%
%%%%
function doPlotAll
ad =getappdata(0, 'GridEditorToolData');
clear_view;
doPlotGrid;
doPlotMeanShape;
doPlotCentroids;
doPlotEdgeSprings;
doPlotSprings;
doPlotShapeSprings;
doToggleAll;
axis(ad.handles.imageAxis, 'image');
