A Point About Polygons

An essay on the aesthetics of polygons and algorithms that one might see in a web image map.

Testing the Algorithm

The test program (Listing 2) draws a random 40-sided polygon
and then picks random points to throw at the
inpoly() routine. Points the routine says are
inside the polygon it draws red, points outside are blue.

Figure 2. A Random 40-Sided Polygon

All Tripped Up

Our first rendition of inpoly() had a
subtle flaw which the test program made evident. The full story
contains an embarrassing lesson. “It'll work,” we sneered, “We
don't need to waste time on a full graphical test. Besides, it'd be
too much fun.” After we found out our image maps had leaks, we
wrote the test program. Figure 3 shows a close-up of the
flaw.

Figure 3. The flaw: The Corner is Counted Twice

Along a vertical line, all the colors are wrong. The flaw
turned out to be that when our mindless mollusk crosses the bottom
corner, the little hummer was counting the crossing of both edges!
After that, he was always exactly wrong—he thought he was in when
he was out, and he thought he was out when he was in. The solution
must ensure that when our esteemed escargot crosses into the
polygon corner, he counts exactly one crossing. Two is no good, and
in fact, zero is just as bad—one is what we need. The reason the
flaw in the close-up extends up from the corner is that the
positive Y axis extends downward in screen coordinates.

I suspect this is a problem unique to the fixed-point world.
I'm sure my fellow point-in-polygon smiths have either lucked out
or dealt with it somehow. At least, I'd like to think so. (A
lie-detector would peg me on that one. This article would be
insufferably smug if I had found leaky corners in any of the other
algorithms.) In my case, I realized I could not blindly count all
crossings of the end point of each of the edges as a crossing. My
first thought was to associate each end point with one—and only
one—edge. This sounds fair and equitable, but like many things
fitting that description, it just plain won't work. A problem turns
up when Agent Snail just lightly nicks the corner of a polygon he's
not inside at all. That's counted as one crossing, hence the snail
report is bunk.

Since I abhor special cases, I sought something that would
work in all cases.

Cutting Corners

Figure 4. Counting Only the Right End of Each Edge

The scheme for getting our faithful friend to count corner
crossings correctly is to always count a crossing of the right end
of each edge, but never the left end (right meaning positive X). In
the figure, the black circles represent points our snail will count
if he crosses; the white circles he won't count. When you put the
polygon together, everything ends up the way we want. Nicking the
corner means he counts either 0 crossings or two crossings. We
don't care which; both are even and our snail knows he's outside.
The circles with ones in them represent points counted once if the
snail crosses them. This is fine, just like crossing the nearby
sides.

It's time to analyze the guts of the
inpoly() routine in Listing 3. This represents a
slight modification of the snail's instructions. He plays a bit of
a “she loves me, she loves me not” kind of game rather than
counting up the crossings and then reporting whether the total is
even or odd. He starts out assuming he's outside, and complements
that assumption with each crossing. So much for the
inside=!inside statement.

This if test happens inside a
for loop that considers all of the edges of the
polygon, one at a time. Each edge is a line segment that stretches
between the corners (xold,yold) and (xnew,ynew). We've arranged it
so (x1,y1) and (x2,y2) also represent the same edge, but the points
are swapped, if necessary, to make it so x1 <= x2.

Now two things must be true for our ever-meticulous snail to
count the crossing of this edge. First, the segment must straddle
the Y axis (where the right end is counted but the left one is
not). Second, straddling has to happen to the north of the snail's
starting point. These are exactly the questions determined by the
if statement's two pieces, on either side of the
&&.

Now that first expression is a sneaky one, and I confess I
might have preferred the less opaque code (x1 < xt && xt
<= x2). You can see it does the same thing if you look carefully
(very carefully—I was fooled for a while there). But I hate to fix
something unless I've already broken it, if you know what I
mean.

That north computation is the one I'm proud of because none
of my esteemed fellow polygon smiths made one that doesn't need a
divide. It does depend on the knowledge that (x2-x1) is positive.
Other than that, it's just a transmogrification of that famous
y=mx+b equation from high school algebra.

By the way, I've left out the case where an edge line segment
stands straight up and down above the snail touchdown point. Such
an edge would never be counted by Mr. Snail at all! That's because
the == test would always be false, since xnew, xt and xold are all
the same value. What's really wild is that's just what we want. In
a sense, he's crossing three edges when we only want to count one.
It turns out the adjacent line segment crossings are all we're
interested in, and the rules already discussed work perfectly for
them.

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.