0% found this document useful (0 votes)
51 views14 pages

Hormann 2001

The document discusses two approaches for solving the point in polygon problem: the even-odd rule and the winding number. It shows that both concepts are closely related by developing an algorithm to determine the winding number. The algorithm works by incrementally summing the signed angles between edges of the polygon and calculating the winding number from the final angle sum. The document also examines accelerating the algorithm and handling special cases like points on polygon edges.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
51 views14 pages

Hormann 2001

The document discusses two approaches for solving the point in polygon problem: the even-odd rule and the winding number. It shows that both concepts are closely related by developing an algorithm to determine the winding number. The algorithm works by incrementally summing the signed angles between edges of the polygon and calculating the winding number from the final angle sum. The document also examines accelerating the algorithm and handling special cases like points on polygon edges.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Computational Geometry 20 (2001) 131–144

www.elsevier.com/locate/comgeo

The point in polygon problem for arbitrary polygons


Kai Hormann a,∗ , Alexander Agathos b
a University of Erlangen, Computer Graphics Group, Am Weichselgarten 9, 91058 Erlangen, Germany
b University of Athens, Department of Informatics, Athens, Greece

Communicated by K. Mehlhorn; received 18 January 2000; received in revised form 9 January 2001; accepted 20 March 2001

Abstract
A detailed discussion of the point in polygon problem for arbitrary polygons is given. Two concepts for solving
this problem are known in literature: the even–odd rule and the winding number, the former leading to ray-crossing,
the latter to angle summation algorithms. First we show by mathematical means that both concepts are very closely
related, thereby developing a first version of an algorithm for determining the winding number. Then we examine
how to accelerate this algorithm and how to handle special cases. Furthermore we compare these algorithms with
those found in literature and discuss the results.  2001 Elsevier Science B.V. All rights reserved.
Keywords: Polygons; Point containment; Winding number; Integer algorithms; Computational geometry

1. Introduction

A very natural problem in the field of computational geometry is the point in polygon test: given a
point R and an arbitrary closed polygon P represented as an array of n points P0 , P1 , . . . , Pn−1 , Pn = P0 ,
determine whether R is inside or outside the polygon P . While the definition of the interior of standard
geometric primitives such as circles and rectangles is clear, the interior of self-intersecting closed
polygons is less obvious. In literature [1,4,5,7,8,10,13,14], two main definitions can be found.
The first one is the even–odd or parity rule, in which a line is drawn from R to some other point S that
is guaranteed to lie outside the polygon. If this line RS crosses the edges ei = Pi Pi+1 of the polygon an
odd number of times, the point is inside P , otherwise it is outside (see Fig. 1(a)). This rule can easily be
turned into an algorithm that loops over the edges of P , decides for each edge whether it crosses the line
or not, and counts the crossings. Various implementations of this strategy exist [2–4,6,8,10–12] which
differ in the way how to compute the intersection between the line and an edge and how this rather costly
procedure can be avoided for edges that can be guaranteed not to cross the line. We discuss these issues
in detail in Section 3.
* Corresponding author.
E-mail addresses: [email protected] (K. Hormann), [email protected] (A. Agathos).

0925-7721/01/$ – see front matter  2001 Elsevier Science B.V. All rights reserved.
PII: S 0 9 2 5 - 7 7 2 1 ( 0 1 ) 0 0 0 1 2 - 8
132 K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144

(a) (b)
Fig. 1. The interior of a self-intersecting polygon based on (a) the even–odd rule and (b) the nonzero winding
number.

The second one is based on the winding number of R with respect to P , which is the number of
revolutions made around that point while traveling once along P . By definition, R will be inside the
polygon, if the winding number is nonzero, as shown in Fig. 1(b). We show that the same result as with
the even–odd rule can be obtained by letting the interior consist of those points whose winding number is
odd. Therefore, both definitions of the interior can be based on the winding number, making this concept
the more general one.
In Section 2 we explain in detail how the incremental angle algorithm [13] for determining the winding
number can be derived mathematically. Further analysis of this algorithm leads to a modification that
turns it into a ray-crossing algorithm, revealing that both concepts are the same in principle. The resulting
algorithm is capable of handling any special cases that might occur, e.g., R may coincide with one of the
vertices Pi of P or may lie on one of P ’s edges ei .
Several methods for accelerating this basic algorithm are discussed in Section 3. Of course the problem
always is of complexity O(n) for arbitrary polygons, hence “acceleration” refers to reducing a constant
time factor. The complexity can only be reduced for special polygons, e.g., if the polygon is convex,
an O(log n) algorithm can be found [7,8,10]. The performance of the different algorithms is analyzed
in Section 4 and a comparison to those found in literature is made. Section 5 summarizes the proposed
ideas.

2. Winding numbers

As stated in Section 1, the answer to the point in polygon problem can be derived from the winding
number. Starting with the mathematical definition of the winding number, we simplify the general
formula step by step until we obtain the pseudo-code of a very intelligible algorithm that determines
the winding number of a point with respect to an arbitrary polygon.
The winding number ω(R, C) of a point R with respect to a closed curve C(t) = (x(t), y(t))T ,
t ∈ [a, b], C(a) = C(b), is the number of revolutions made around R while traveling once along C,
provided that R is not visited in doing so. Whenever there exists t˜ ∈ [a, b] such that C(t˜) = R, the
winding number ω(R, C) is undefined. Otherwise it can be calculated by integrating the differential of
the angle ϕ(t) between the edge RC(t) and the positive horizontal axis through R (cf. Fig. 2(a)). As C(t)
is a closed curve, this always yields ω · 2π with ω ∈ Z denoting the winding number.
K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144 133

Fig. 2. (a) The continuous angle ϕ(t) for curves. (b) The discrete signed angle ϕi for polygons.

Without loss of generality we assume R = (0, 0) so that ϕ(t) = arctan(y(t)/x(t)) and


b b b
1 1 dϕ 1 ẏ(t)x(t) − y(t)ẋ(t)
ω(R, C) = dϕ(t) = (t) dt = dt. (1)
2π 2π dt 2π x(t)2 + y(t)2
a a a

A closed polygon P represented as an array of n points P0 , P1 , . . . , Pn−1 , Pn = P0 can be seen as a


piecewise linear curve t → (xi (t − i), yi (t − i))T , t ∈ [i, i + 1], with (xi (t), yi (t))T = tPi+1 + (1 − t)Pi .
Using Eq. (1) and Appendix A we obtain

n−1  1
1  ẏi (t)xi (t) − yi (t)ẋi (t)
ω(R, P ) = dt
2π i=0 xi (t)2 + yi (t)2
0
  
1 n−1
Pi |Pi+1  Px x 
Pi+1
= arccos · sign  iy  (2)
Pi  Pi+1  Pi+1 
y
2π i=0
Pi
1 
n−1
= ϕi , (3)
2π i=0

where ϕi is the signed angle between the edges RPi and RPi+1 (cf. Fig. 2(b)).
Eq. (2) can be used for creating an algorithm for computing the winding number but it involves
expensive calls to the arccos and sqrt routines. Although these can be accelerated by using lookup-tables
and nearest-neighbor interpolation, as we can eliminate rounding errors by rounding the final result to
the nearest integer value, this still remains a comparatively slow algorithm.
Further simplification of Eq. (3) can be achieved by considering the rounded partial sums sj =
1 j
4
 i=0 π/2  with ω(R, P ) = 
ϕi
sn−1 . This is equivalent to counting only quarter-revolutions and can be
realized as follows. Based on an algorithm that is explained on p. 251 of Rogers’ book [9] for testing
134 K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144

Fig. 3. Classification of vertices Pi by quadrants, e.g., Fig. 4. Example of half ccw- or cw-revolution: edge e3
q3 = 0, q4 = 1 and q5 = 2. with δ3 = 2 is ccw, e4 with δ4 = −2 is cw.

whether a polygon surrounds a rectangular window or is disjoint to it, we classify each vertex Pi of the
polygon P by the number qi of the quadrant in which it is located with respect to R (cf. Fig. 3), i.e.,
 
  
 [0, π/2) 
    

 
 

 0    > 
  y 
 [π/2, π ) 
 
  
 
1 Pi  y >
qi = , if arctan ∈ , resp. Pix R x , Pi Ry .

 2 Pix  [π, 3π /2) 
  <  
   
 


   
  

  
3  [3π /2, 2π ) 
 <

Now we can define the quarter angle 1 δi = qi+1 − qi , i = 0, . . . , n − 1, for each of the polygon’s edges
ei . If δi = 0, then the corresponding edge is located wholly in one quadrant and nothing happens. If
δi ∈ {1, −3}, the edge crosses one of the quadrant boundaries in counter-clockwise (ccw) direction and
a quarter ccw-revolution around R is made, while the reverse holds for δi ∈ {−1, 3}. If δi ∈ {2, −2}, a
further check is required to decide whether a half ccw- or cw-revolution around R occurs by moving
along the corresponding edge ei (cf. Fig. 4). This can be done by checking the orientation of the triangle
(R, Pi , Pi+1 ), i.e., by finding the sign of the determinant,
 x   
 P − Rx x
Pi+1 − R x  + ccw
sign  i = ⇐⇒ .
Pi+1 − R y 
y y
Pi − R y − cw
By further introducing the adjusted quarter angles δi via the table

δi 
δi
0 0
1, −3 1
−1, 3 −1
2 ccw, −2 ccw 2
2 cw, −2 cw −2

1 Because of 0  q  3 we know that −3  δ  3.


i i
K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144 135

 evaluation of the determinant 


function det (i)
y y
return (Pix − R x ) ∗ (Pi+1 − R y ) − (Pi+1
x
− R x ) ∗ (Pi − R y )
 quadrant classification 
for i = 0 to n−1
y
if Pix > R x and Pi  Ry : qi = 0
y
if Pix  R x and Pi > Ry : qi = 1
y
if Pix < R x and Pi  Ry : qi = 2
y
if Pix  R x and Pi < Ry : qi = 3
qn = q0
 determination of winding number 
ω=0
for i = 0 to n − 1
switch qi+1 − qi :
1, −3: ω = ω + 1
−1, 3: ω = ω − 1
2, −2: ω = ω + 2 ∗ sign of det (i)
return ω/4

Algorithm 1. First version of a winding number algorithm.

we can sum up these δi to count the number of quarter ccw-revolutions around R and get
1  1
j n−1
sj =
 δi ⇒ ω(R, P ) = sn−1 = δi .
4 i=0 4 i=0
This leads to the first version of a winding number algorithm (Algorithm 1) which resembles the
incremental angle algorithm in [13]. It can further be improved by exploiting the following observation:

n−1 
n−1
1n−1
 
δi = (qi+1 − qi ) = qn − q0 = 0 ⇒ ω(R, P ) = δi − δi ,
i=0 i=0
4 i=0

i.e., we just need to sum up the differences δi − δi , which are nonzero only for δi ∈ {−3, −2, 2, 3}. 2 Thus,
by defining

 1, if δi ∈ {−3, −2 ccw},
δ̄i = −1, if δi ∈ {3, 2 cw},

0, else,
we get

n−1
ω(R, P ) = δ̄i ,
i=0

2 And we have 
δi − δi = ±4 in these cases.
136 K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144

..
.
ω=0
for i = 0 to n − 1
switch qi+1 − qi :
−3: ω = ω + 1
3: ω = ω − 1
−2: if det (i) > 0: ω = ω + 1
2: if det (i) < 0: ω = ω − 1
return ω
Algorithm 2. Modification of Algorithm 1.

Fig. 5. All edges (arrows indicating direction from Pi to Pi+1 ) crossing from below the ray to above are counted
+1 (a), the others −1 (b).

which results in a slight modification of the first algorithm (Algorithm 2) and improves the performance
by approximately 5%.
However, besides this small acceleration it is far more important to notice that the algorithm has now
turned into a ray-crossing method. In fact, by disregarding all edges
 with δi ∈ {−1, 1}, the remaining
cases relate to edges that cross the horizontal ray 3  = {R + λ 10 , λ  0}. The difference to the even–
odd rule where only the number of crossings is counted is that edges starting below this ray and ending
above it are counted +1 and the others −1 (cf. Fig. 5). Nevertheless, the winding number ω still shifts
from even to odd and back with every crossing, so that testing the parity of ω exactly gives the even–odd
definition.
Therefore, we have presented an algorithm that is capable of solving the point in polygon problem for
both definitions of the interior of an arbitrary polygon: the one based on the even–odd rule and the other
based on the nonzero winding number. In contrast to the statement of O’Rourke, that the determination
of the winding number depends on “floating-point computations, and trigonometric computations in
particular” [8], this algorithm gets by with integer arithmetic except for the det function which needs
floating-point operations if the coordinates are non-integer. However, divisions (neither integer nor
floating-point) are totally avoided.
 
3 This refers to the special choice of S = +∞ in the definition of the even–odd rule.
Ry
K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144 137

Fig. 6. Degenerate intersections of  and P .

Another advantage of this algorithm is the handling of degenerate cases, which can cause trouble in
other algorithms, as, e.g., Foley et al. point out that “the ray must hit no vertices of the polyline” [1].
However, the quadrant-classification of the vertices Pi naturally avoids these degeneracies. In Fig. 6, the
regular polygon segment P1 , P2 as well as the degenerate segment sequence P6 , P7 , P8 , P9 should count
+1, while the sequence P4 , P5 , P6 should count −1 and P2 , P3 , P4 should not be regarded as a crossing
at all, thus resulting in ω(R, P ) = 1.
The classification scheme guarantees that no vertex can ever coincide with the ray , because either
y y
Pi  R y , then Pi is above the ray, or Pi < R y which holds for all vertices lying below . Therefore, the
edges e2 , e3 , e4 and e7 are ignored as all the vertices adjacent to these edges are classified as 0-quadrant-
vertices. On the other hand, edges e1 and e6 will be recognized as positive crossings (δ̄1 = δ̄6 = 1) and e5
as a negative one (δ̄5 = −1). All other edges, including e8 do not affect the determination of ω(R, P ).
Another important feature of the algorithm is that it can easily be modified to recognize the special
case of R lying on the boundary of P , which may lead to ambiguities in some other algorithms. We
distinguish two different cases: firstly, R may coincide with one of the vertices Pi of P , which can be
detected by inserting the line
y
if Pix = R x and Pi = R y : exit vertex_code

into the quadrant classification loop. Secondly, R may lie on one of P ’s edges ei . In this case, the angle
between RPi and RPi+1 is always ±π , so that the classification scheme assigns two diagonally opposite
quadrants (0 and 2, or 1 and 3) to the vertices Pi and Pi+1 , hence δi = qi+1 − qi = ±2. This always
invokes the det function, which returns 0 in this case. Thus, by replacing this function with

function det (i)


y x − R x ) ∗ (P y − R y )
d = (Pix − R x ) ∗ (Pi+1 − R y ) − (Pi+1 i
if d = 0
exit edge_code
else
return d

the algorithm is able to detect this case, too. In the remainder we will refer to this modification as the
boundary version.
138 K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144

function classify (i) ω=0


y
if Pi > R y for i = 0 to n − 1
return (Pix  R x )  horizontal line crossed? 
y y
else if (Pi < R y and Pi+1  R y ) or
y
if Pi < R y y y
(Pi  R y and Pi+1 < R y )
return 2 + (Pix  R x )  crossing to the right? 
else y y
if (det (i) > 0 and Pi+1 > Pi ) or
if Pix > R x y y
(det (i) < 0 and Pi+1 < Pi )
return 0
 modify winding number 
else y y
if Pix < R x if Pi+1 > Pi
ω=ω+1
return 2
else
else ω=ω−1
exit vertex_code return ω
Algorithm 3. Efficient quadrant classification. Algorithm 4. Computing the winding number without
quadrant classifications.

3. Efficient implementation

For many applications the algorithms of the previous section are sufficient. They are robust, correct and
easy to understand which always helps to reduce the probability of an implementation bug. But in other
applications this routine might be called so often that it turns out to be a bottleneck. We now discuss how
the basic algorithms can be accelerated, ending up with two very efficient versions: the efficient standard
algorithm, that is very short but does not care about the special case of R lying on the boundary of P and
the efficient boundary algorithm, that needs a little more code but handles that special case.
Looking at Algorithms 1 and 2, there are three parts that can be improved: the det function, the
quadrant classification and the determination of the winding number. The det function can be declared
as inline which saves a few clock cycles for the function call but there is no way to accelerate the
actual calculation of this determinant. Likewise one can try to break up the switch structure in the third
part into a series of sophisticated if/else statements but this does not really accelerate the algorithm
considerably.
However, the quadrant classification can be improved a lot. In the present version, the average number
of comparisons that have to be evaluated for each vertex is 6, assuming the compiler generates short
circuit evaluation 4 . By simply adding an else statement to the end of each line this number can be
reduced to 4. A more sophisticated decision tree which only needs slightly more than 2.5 comparisons
per vertex and is also able to detect the case of vertex coincidence is shown in Algorithm 3. Note that we
have followed the C convention that logical expressions are equal to 1 if they are true and 0 otherwise
in order to reduce the length of the code. The use of this classification variant accelerates the basic
algorithms of the previous section by more than 30% (cf. Fig. 11).
Unfortunately this is the maximum speed-up we can get out of our basic idea and we need to restructure
the algorithm for further improvement. First of all we can combine the two loops because both of them

4 I.e., the second operand of an and operator is only evaluated if the first one is true.
K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144 139

Fig. 7. Edges that fulfill the crossing condition.

range over the same interval i = 0, . . . , n − 1. Then we can eliminate the array q as we can process
the quadrant numbers on the fly and do not need an explicit storage of these values. All we need for
each single pass of the loop are the quadrant numbers of the vertex where the edge ei that is currently
processed begins and the one where it ends, namely qb and qe . This leads to the following simplification:
qb = classify (0)
for i = 0 to n − 1
qe = classify (i + 1)
switch qe − qb :
..
.
qb = qe

and reduces memory usage as well as execution time.


Further optimization can be achieved by omitting the quadrant numbers altogether and rather handling
the cases in which the winding number changes directly. All edges ei that relate to these cases have in
common that one of their endpoints lies strictly below the horizontal line through R and the other one
above or on it (cf. Fig. 5). After using this property as an initial test to distinguish edges that might
contribute to a change in the winding number from those who certainly do not, the edge constellations
shown in Fig. 7 remain. To further reject those edges that do not modify the winding number, the
following observation can be used. Whenever the determinant does not have the same sign as the
y y
difference Pi+1 − Pi , the intersection of the edge with the horizontal line is on the left side of R and the
winding number remains unchanged. For the residual edges, the edge direction decides the sign of the
y y
modification: if the edge crosses the horizontal line from below (Pi+1 > Pi ), then the winding number is
increased, otherwise it is decreased. These considerations are summarized in Algorithm 4, which is 20%
faster than Algorithm 2 with the optimal classification scheme (Algorithm 3). This code can be abridged
a lot by using the following macros which may seem a little cryptic at first sight:
y y
crossing: (Pi < R y ) = (Pi+1 < R y ),
y y
right_crossing: (det (i) > 0) = (Pi+1 > Pi ),
y y
modify_ ω: ω = ω + 2 ∗ (Pi+1 > Pi ) − 1.

They can be used to rewrite Algorithm 4 as Algorithm 5 and accelerate it by more than 30%.
The last improvement on the winding number algorithm can be made by avoiding the rather costly
procedure of computing the determinant whenever possible. In Algorithm 5 the determinant computation
is invoked for all edges that pass the crossing test in order to find out whether they intersect the
horizontal line to the left or to the right of R. But for some of these edges this decision can be made in a
140 K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144

ω=0
for i = 0 to n − 1
if crossing
if Pix  R x
x
if Pi+1 > Rx
modify_ ω
else
ω=0 if right_crossing
for i = 0 to n − 1 modify_ ω
if crossing else
x > Rx
if Pi+1
if right_crossing
modify_ ω if right_crossing
return ω modify_ ω
return ω
Algorithm 5. Using macros to
rewrite Algorithm 4. Algorithm 6. Efficient standard algorithm.

Fig. 8. Different cases of edge coincidences.

simpler way. Referring to Fig. 7, edges like the leftmost one (Pix < R x and Pi+1x
 R x ) never change the
winding number, whereas those similar to the rightmost one (Pi  R and Pi+1 > R x ) always do. Both
x x x

cases can be detected by comparisons and only the edges in the middle require the evaluation of the det
function to decide whether they affect the winding number or not. This observation has been realized
in the efficient standard algorithm (Algorithm 6). Assuming uniformly distributed polygon vertices, the
probability of occurrence of the different edge types is 25% for the leftmost, 25% for the rightmost case
and 50% for the edges shown in the middle. Therefore Algorithm 5 evaluates the det function only
every second time on average. This improvement is traded in for two extra comparisons and decreases
the computational costs by approximately 5%.
Now we will show that only minor modifications of the efficient standard algorithm are necessary in
order to handle special cases. First of all, most cases of edge coincidences can be detected by using the
modified det function in the right_crossing condition. Only the case of R lying on a horizontal
edge (leftmost case in Fig. 8) cannot be recognized this way because this constellation does not pass the
crossing condition and can therefore never reach the call of the det function. The other special case,
R being identical to one of the vertices Pi , can be detected by checking the equality of both coordinates as
in the boundary version of Algorithm 1. The resulting code is shown in Algorithm 7. Note that the vertex
coincidence test is prior to the investigation of possible ray intersections, because an edge intersection
could be wrongly detected otherwise.
K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144 141

y
if P0 = R y and P0x = R x
exit vertex_code
ω=0
for i = 0 to n − 1
y
if Pi+1 = R y
x
if Pi+1 = Rx
exit vertex_code
else
y
if Pi = R y and (Pi+1
x > R x ) = (P x < R x )
i
exit edge_code
if crossing
if Pix  R x
if Pi+1x > Rx

modify_ ω
else
if right_crossing
modify_ ω
else
if Pi+1x > Rx

if right_crossing
modify_ ω
return ω
Algorithm 7. Efficient boundary algorithm.

4. Evaluation

The timings reported in this section refer to an implementation in C on a 195 MHz SGI R10000 with
128 MB of memory, but similar results were obtained by using Pascal and a Pentium PC with 233 MHz
and 64 MB of memory. We generated 1000 polygons for different values of n and determined the winding
numbers of 1000 reference points for each of these polygons, thus calling the winding number algorithm
one million times. The vertices of the polygons as well as the reference points were chosen randomly
within the integer square [−100, 100] × [−100, 100].
Fig. 9 shows that the runtime of the standard algorithms that do not take the special cases into account
grows linear with the number of vertices, thus confirming the O(n) complexity of the problem. In
contrast, the boundary algorithms behave different (see Fig. 10). As the number of vertices grows, the
probability of the reference point to lie on the boundary of the polygon increases. At the same time the
chances of the boundary algorithm to exit earlier with the detection of a vertex or an edge coincidence
rise and therefore the algorithms do not need to run through the whole loop over the polygon’s edges in
many cases. Of course, this effect is much less perceivable if the reference points are chosen from a larger
domain than the polygon vertices or if the coordinates are floating-point values. Fig. 11 summarizes the
timing results of all algorithms for the special choice of n = 10.
All algorithms presented in this paper can easily be modified to give the result of the even–odd
rule instead of the winding number by replacing every statement that modifies ω, especially the macro
modify_ ω, with ω = 1 − ω. This simplification saves about 5% of the computation time.
Furthermore we would like to mention that the algorithms can be speeded up considerably by
comparing the reference point with the polygon’s bounding box first, as it is done, e.g., in the point in
142 K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144

Fig. 9. Execution times of the algorithms that do not handle the special cases.

Fig. 10. Execution times of the algorithms that handle the special cases.

polygon algorithm of the C++ library LEDA [6]. The additional costs of the bounding box determination
and the test itself pay off after just a few (< 10) tests, the precise number depending on the number of
vertices as well as the size of the reference point domain compared to the size of the polygon.
We conclude this section by comparing our algorithms to those found in literature. The most thorough
comparison of different point in polygon strategies was probably made by Haines in [4], with the result
that the ray-crossing strategy performs best “if no preprocessing nor extra storage is available”. Taking a
close look at his ray-crossing algorithm it is very similar to Algorithm 6, except that he uses a different
K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144 143

Fig. 11. Execution times of all algorithms for n = 10.

test for determining whether an edge crosses the ray to the right. He directly computes the x coordinate
of the intersection and compares it to R x ,
x − (P y y y
i+1 − R ) ∗ (Pi+1 − Pi )/(Pi+1 − Pi ) > R .
right_crossing’: Pi+1 y x x x

y y
Note that the case of Pi+1 = Pi , which would cause a division by zero, never passes the prior crossing
test. We found this version to be approximately 8% slower than the right_crossing condition in our
testing environment, which is probably due to the division operation. This observation corresponds with
Haines’ comments on a modified version of his algorithm [3] where he uses the right_crossing
condition. At the same time he omits the if-statements that filter unnecessary evaluations of this condition,
making that modified version identical to Algorithm 5.
The right_crossing’ condition has also been used in an implementation by Franklin [2] which is
otherwise identical to Algorithm 5, as are the algorithm in the LEDA library [6] and the implementation
y y
by Stein [11] except that they swap Pi and Pi+1 if necessary so that they can always assume Pi+1 < Pi
which simplifies the right_crossing condition to (det (i) < 0) but is about 20% slower in total.
Finally, the code given by O’Rourke [8] resembles Algorithm 4 with a right_crossing’ condition
and he gives further optimization ideas as exercises which will eventually lead to Algorithm 5.

5. Conclusion

We have presented a detailed discussion of the point in polygon problem for arbitrary polygons. This
problem is well known and has been discussed in many books and papers before. Most of the authors
distinguish between two concepts for solving this problem: the even–odd or parity rule and the nonzero
winding number. We have shown by mathematical means that both concepts are the same in principle
and that the concept of winding numbers encompasses the even–odd idea.
Furthermore, we have developed an algorithm for the determination of the winding number and have
improved it step by step up to a very efficient implementation. We have compared our algorithms to
those found in literature and can summarize that in our testing environment Algorithm 6 performed best
although we admit that Algorithm 5 and the implementations in [2–4] were so close that they might be
faster for different machine architectures and compilers. However, a definite advantage of our approach
144 K. Hormann, A. Agathos / Computational Geometry 20 (2001) 131–144

is that it can easily be extended to handle the special case of R lying on the boundary of P (Algorithm 7),
an issue that was otherwise taken care of only in [6] and [8], leading to much slower algorithms.

Appendix A

Let R = (0, 0)T , P = (Px , Py )T and Q = (Qx , Qy )T be the vertices of a planar triangle and α, β, γ the
angles of that triangle at R, P and Q, respectively. Then
P |Q P − Q|P  Q − P |Q
cos α = , cot β = , cot γ = ,
P  Q |D| |D|
with D = Px Qy − Qx Py and for the linear curve (x(t), y(t))T = tQ + (1 − t)P , t ∈ [0, 1], the following
equations hold:
1 1
ẏ(t)x(t) − y(t)ẋ(t) D
dt = dt
x(t)2 + y(t)2 t 2 Q − P |Q − P  + 2t Q − P |P  + P |P 
0 0
Q − P |Q P − Q|P 
= arctan + arctan
D D
= sign(D)(arctan cot γ + arctan cot β)
= sign(D)(π − γ − β)
= sign(D)α.

References

[1] J.D. Foley, A. van Dam, S.K. Feiner, J.F. Hughes, Computer Graphics: Principles and Practice, 2nd Edition,
Addison-Wesley, 1990.
[2] R. Franklin, pnpoly, http://www.ecse.rpi.edu/Homepages/wrf/geom/pnpoly.html.
[3] E. Haines, CrossingsMultiplyTest, http://www.acm.org/tog/GraphicsGems/gemsiv/ptpoly_haines/ptinpoly.c.
[4] E. Haines, Point in polygon strategies, in: P. Heckbert (Ed.), Graphic Gems IV, Academic Press, Boston, MA,
1994, pp. 24–46.
[5] S. Harrington, Computer Graphics: A Programming Approach, McGraw-Hill, 1983.
[6] K. Mehlhorn, S. Näher, LEDA: A Platform for Combinatorial and Geometric Computing, Cambridge
University Press, 1999.
[7] J. Nievergelt, K. Hinrichs, Algorithms and Data Structures: With Applications to Graphics and Geometry,
Prentice-Hall, 1993.
[8] J. O’Rourke, Computational Geometry in C, 2nd Edition, Cambridge University Press, 1998.
[9] D.F. Rogers, Procedural Elements for Computer Graphics, McGraw-Hill, 1985.
[10] R. Sedgewick, Algorithms, 2nd Edition, Addison-Wesley, 1988.
[11] B. Stein, A point about polygons, Linux Journal 35 (March 1997).
[12] T. Theoharis, A. Böhm, Computer Graphics: Principles & Algorithms, Symmetria, 1999 (in Greek).
[13] K. Weiler, An incremental angle point in polygon test, in: P. Heckbert (Ed.), Graphic Gems IV, Academic
Press, Boston, MA, 1994, pp. 16–23.
[14] M. Woo, J. Neider, T. Davis, OpenGL Programming Guide, 2nd Edition, Addison-Wesley, 1997.

You might also like