Alright, let's take a closer look at polygons.

We'll call him Ted. When Ted (or a polygon in general) sees a point, he tries to assimilate it within himself. And for assimilation, he decides to give one of his many sides the honor of reaching out and grabbing the point. Now, Ted is busy with more important stuff, so the sides need to decide among themselves which one will do the good deed. I'll say it again; sides.

There we go, there's a point in Ted's vicinity, blissfully unaware that soon it's going to be consumed viciously. So, how do Ted's sides decide which one will snatch the point? Well, it needs to be fair game. The side which senses that the perpendicular distance from it to the point is the shortest will be the one to do it. Shortest. Perpendicular. Distance.

Assimilation complete!
Another thing to keep in mind is that polygons like Ted value survival over assimilation. The side with the shortest perpendicular distance from the point commences the assimilation only if it does not cut through the other sides. So, sides with only valid assimilation are considered. Otherwise, bad things happen.

There are two important points within my unnecessary spiel;
- The side to which we add the point should have the shortest perpendicular distance from the point.
- Apart from having the shortest perpendicular distance from the point, the addition of the point to this side should be valid. This is important, after all, we don't want to perpetrate mass polygon murder.
So, here's some pseudo-code;
For each side S in polygon P
Do
d := perpendicularDistanceFromSide(S, point);
If d is less than shortestPerpendicularDistance
Do
If additionIsValid(S, point, P)
Do
shortestPerpendicularDistance := d;
index = S.index;
End If
End If
End For
Finding the perpendicular distance from the side is easily done;
var perpendicularDistance = function(side, point) {
//Find direction vector of side
var dir = {x: side.p2.x - side.p1.x, y: side.p2.y - side.p1.y};
var m = Math.sqrt(dir.x*dir.x + dir.y*dir.y);
if(m !== 0) {
d.x = d.x/m;
d.y = d.y/m;
}
//Find position vector of point, from side
var pVec = {x: point.x - side.p1.x, y: point.y - side.p1.y};
//Absolut of cross product of dir and pVec.
//It's essentially |pVec|*Sin(q), q is the angle between
//dir and pVec.
return Math.abs(dir.x*pVec.y - dir.y*pVec.x);
};
Now, let's look at validity. If, after adding the point to the polygon, the new sides cut through any of the other sides, it's over for the little guy. We need to ensure that our algorithm accounts for this.
I thought up two versions for this; one cheap and one expensive.
Method 1:
If there is little to none concavity in the polygon, this method works perfectly. This method only checks that the new sides do not intersect the sides adjacent to the old side.
Say we have a side S
. It's two adjacent sides are Sprev
and Snext
. The two new sides are S1p
and S2p
. S1p
and Sprev
have the point S.p1
in common. S2p
and Snext
have the point S.p2
in common.
According to this method, the addition is valid if and only if there is no intersection between:
Sprev
and S2p
Snext
and S1p
So, this method works on rejection. If we can't find any intersection, the side S
can add the point validly.
Method 1 Demo
Method 2:
Method 1 fails as the concavity of the polygon increases. So, we need to do further checking to ensure valid point addition.
This method is really an extension of Method 1. After finding that the pairs Sprev
and S2p
, and Snext
and S1p
are not intersecting, we check if the new sides are intersecting with all the other sides of the polygon (apart from Sprev
and Snext
, of course).
If the addition is not rejected after all the sides are checked, we are completely sure that this addition is valid.
The problem is, that while rejection is quick enough, reaching acceptance takes a long time, making this method quite expensive.
Furthermore, the complexity depends on the number of sides of the polygon. As the polygon complexity increases, checking validity will take more and more time.
Method 2 Demo
I must note, the algorithm I used for checking line-segment intersection is taken from How do you detect where two line segments intersect?. It's totally awesome.
And that's all I have. This is one way to do it, I must say. There might be another, better way which has not struck me yet. I hope you didn't terribly mind Ted. And also, thanks for asking a good question, I enjoyed it.