function [shape_image] = contour2shape_v2(vertices, width, height)
% -------------------------------------------------------------------------
% MSc Project - MSc in Communications and Signal Processing
% Department of Electrical and Electronic Engineering
% Imperial College London, 2011
%
% Supervisor  : Dr Pier Luigi Dragotti
% Contributor : Andriy Gelman
% Author      : Jon Onativia Bravo
%
% File        : contour2shape.m
% -------------------------------------------------------------------------
% Create a binary shape from a list of vertices.
%
% [shape_image] = contour2shape(vertices, width, height)
%
% INPUT:
%  - vertices    : List of vertices (2xN) with first element of each 
%                  segment corresponding to [0; segment_length].
%  - width       : Width in pixels of the output image.
%  - height      : Height in pixels of the output image.
%
% OUTPUT:
%  - shape_image : width x height binary shape image.
%


% Output parameters
shape_image = false(height, width);


% Get different segments information
segment_inds = find(vertices(1,:) == 0);
seg_lengths  = vertices(2,segment_inds);
num_of_segs  = length(segment_inds);


% Compute the points that are inside the polygon defined by this segment

contours    = cell(num_of_segs, 1);
first_verts = zeros(2, num_of_segs);

% Loop through all segments to recreate the contours
for i_seg = 1 : num_of_segs
    % Retrive the segment
    seg_len   = seg_lengths(i_seg);
    seg_start = segment_inds(i_seg) + 1;
    seg_end   = seg_start + seg_len - 1;
    seg       = vertices(:,seg_start:seg_end);
    
    % Store the first real vertex
    first_verts(:,i_seg) = seg(:,1);
    
    % Check if the contour touches the border of the image
    if seg(1,1) == 1
        seg = [ [0; seg(2,1)], seg];
        if seg(1,end) == 1
            seg = [ seg, [0; seg(2,end)] ];
        else
            if seg(2,end) == 1
                seg = [ seg, [seg(1,end); 0], [0; 0] ];
            elseif seg(2,end) == height
                seg = [ seg, [seg(1,end); height+1], [0; height+1] ];
            end
        end
    elseif seg(1,1) == width
        seg = [ [width+1; seg(2,1)], seg ];
        if seg(1,end) == width
            seg = [ seg, [width+1; seg(2,end)] ];
        else
            if seg(2,end) == 1
                seg = [ seg, [seg(1,end); 0], [width+1; 0] ];
            elseif seg(2,end) == height
                seg = [ seg, [seg(1,end); height+1], [width+1; height+1] ];
            end
        end
    elseif seg(2,1) == 1
        seg = [ [seg(1,1); 0], seg ];
        if seg(2,end) == 1
            seg = [ seg, [seg(1,end); 0] ];
        else
            if seg(1,end) == 1
                seg = [ seg, [0; seg(2,end)], [0; 0] ];
            elseif seg(1,end) == width
                seg = [ seg, [width+1; seg(2,end)], [width+1; 0] ];
            end
        end
    elseif seg(2,1) == height
        seg = [ [seg(1,1); height+1], seg ];
        if seg(2,end) == height
            seg = [ seg, [seg(1,end); height+1] ];
        else
            if seg(1,end) == 1
                seg = [ seg, [0; seg(2,end)], [0; height+1] ];
            elseif seg(1,end) == width
                seg = [ seg, [width+1; seg(2,end)], [width+1; height+1] ];
            end
        end
    end
    
    contours{i_seg} = seg;
end

% Compute the coordinates of all the points of the image
row_x = 1:width;
X     = repmat(row_x, height, 1);
col_y = 1:height;
Y     = repmat(col_y, 1, width);

% Create the output image from the contours
for i_seg = 1 : num_of_segs
    seg = contours{i_seg};
    
    % Check if it's an external contour or an inside hole contour. If it's
    % an internal contour, all the vertices will be inside of one of the
    % other contours.
    first_vert          = first_verts(:,i_seg);
    is_internal_contour = false;
    for i_other_seg = 1 : num_of_segs
        if i_other_seg ~= i_seg
            other_seg = contours{i_other_seg};
            [in, on] = inpolygon(first_vert(1), first_vert(2), other_seg(1,:), other_seg(2,:));
            if in == true && on == false
                is_internal_contour = ~is_internal_contour;
            end
        end
    end
    
    % Use the 'inpolygon' function except if the segment is a single pixel
    if size(seg, 2) > 1
        [in, on] = inpolygon(X, Y, seg(1,:), seg(2,:));
    else
        in = false(height, width);
        on = in;
        in(seg(2,:),seg(1,:)) = true;
        on(seg(2,:),seg(1,:)) = true;
    end
    
    % If the contour corresponds to the external contour, remove the
    % 'on' pixels.
    if is_internal_contour == false
        in = xor(in, on);
    end
    
    % Insert the points in the shape image
    shape_image = xor(shape_image, in);
    
end

