function insidePoly = pointWithinPolygon(px, py, point, plotResults)

% Check if a given point is contained with a polygon defined by px and py.
%
% Vipul Lugade
% Matlabgeeks.com
% 9/18/2018
%
% Test cases:
% Polygon defined as:
% px = [0, 1,-1,-1,2,2,3,4];
% py = [0, -1,-1,1,2,4,4,1];
% errorPoint = [1,1];
% pointInside = [2,1];
% pointOutside = [0,3];

%% Error check arguments
if numel(px) ~= numel(py) || numel(px) < 3
    error('Incorrectly defined Polygon');
end
if numel(point) ~= 2
    error('Incorrectly defined point');
end

%% Generate ray from outside polygon to the point in question.
outsidePoint = [min(px) - 1, min(py) - 1];
ray = [outsidePoint; point];

% ensure that ray does not intersect with poygon vertices and modify the
% outside point if it does so.
checkVert = true;
while checkVert
    for k = 1:numel(px)
        onRay = checkPointOnSegment(ray, [px(k), py(k)], false);
        if onRay
            outsidePoint = outsidePoint - rand(1,2);
            ray = [outsidePoint; point];
            break
        end
        if k == numel(px)
            checkVert = false; 
        end
    end
end

%% Check the intersection of each segment with the ray 
count = 0;
for k = 1:numel(px)
    if k < numel(px)
        doesIntersect = checkSegmentIntersection(ray, [px(k) py(k); px(k+1) py(k+1)], false);
    else
        doesIntersect = checkSegmentIntersection(ray, [px(k) py(k); px(1) py(1)], false);
    end
    if doesIntersect
        count = count + 1;
    end
end

%% Check number of intersections.
if mod(count,2) == 0
    insidePoly = false;
else
    insidePoly = true;
end

%% Plot the results if requested.
if plotResults
    figure; hold on;
    plot(px,py,'ro-')
    plot([px(1) px(end)], [py(1) py(end)], 'r-');
    plot(point(1), point(2), 'kx');
    if insidePoly 
        textPoint = 'Inside Polygon';
    else
        textPoint = 'Outside Polygon';
    end
    text(point(1), point(2), textPoint);
end
