You are on page 1of 7

Ray Casting Algorithm - Vinsol

If youve been struggling with the problem of determining whether a point lies
inside or outside a polygon, perhaps in google maps, read on. This post is
specific to Android and Node.js but the algorithm can easily be implemented in
any other language/platform as the algorithm itself is a piece of cake once
understood.
To further elaborate the problem, take a look at the diagram below:

Here we have an irregular polygon (yellow region) and points a, b, c and d.


We have to programmatically determine whether these points lie inside the
polygon or outside. At first glance this might sound trivial, and yes it is, but the
solution provided in Google Maps api is not good enough for most of the
cases.
Solution provided in Google Maps api
Google Maps api considers a super-rectangle that contains all the bounding
points of the given polygon and then determines if the point lies inside this
rectangle or not. This would work great if the polygon is close to a rectangle or
square in shape but not for anything else (definitely not for our Yellow polygon
above). Although their method is not as simple as it sounds. It considers the

earths curvature and the fact that earth is a skewed sphere. Great! But the
precision thats lost during patching a super-rectangle over our innocent
irregular polygon would leave you in tears. Diagram below shows the superrectangle in gray.

Now you do see the problem, right? Point b and c will be considered inside
the polygon while they are not.

Ray Casting Algorithm


Its a concept in computational geometry that lets you determine if a point lies
inside a bounded region by casting infinitely long ray from the given point to
see how many edges of the given polygon this ray intersects. If the number of
intersections is 0 or an even number, the point lies outside the polygon
otherwise inside.
Following illustration shows how Ray casting solves the problem we discussed
above.

It shows that rays from point b and c are having 0 or even number of
intersections, no matter in which direction you draw a line starting from it,
concluding that they lie outside the polygon.

My Implementations of RayCast
Android
https://github.com/Infernus666/RayCast-android
In the above github repository, RaycastHelper.java contains the
implementation of RayCast Algorithm. You have to provide LatLngs or points
as vertices of the polygon in correct clockwise or anticlockwise sequence. The
solution also assumes that the LatLngs or points you provide form a closed
polygon. It exposes following 2 static methods:

1. boolean isLatLngInside(ArrayList latLngs, LatLng


latLng)
This method is optimised for geo-locations. Ray-casting algorithm works for a
linear surface and earth is spherical. So, before going for ray-casting, this
method normalises the provided latlngs for a 2-D plain by settling the
irregularity in longitudes near International Date Line ( -178, -179, 179, 178
).
2. boolean isPointInside(ArrayList points, Point point)
This can be used for any X-Y plane. Point is class provided in the above repo
to represent a point in an x-y plane.
ArrayList<LatLng> polygonVertices = new ArrayList<>();

polygonVertices.add(new LatLng(28.635789, 77.215029));

polygonVertices.add(new LatLng(28.638086, 77.220952));

polygonVertices.add(new LatLng(28.634621, 77.225758));

polygonVertices.add(new LatLng(28.634771, 77.221467));

polygonVertices.add(new LatLng(28.632662, 77.225114));

polygonVertices.add(new LatLng(28.629724, 77.220265));

polygonVertices.add(new LatLng(28.631796, 77.215265));

LatLng latLng = new LatLng(28.631666, 77.218333);

boolean isLatLngInside = RaycastHelper.isLatLngInside(polygonVertices, latLng);

view rawandroidRcSample.java hosted with

by GitHub

Nodejs
https://www.npmjs.com/package/raycast
npm install raycast
This npm package provides the same two methods described in the Android
section above. The package also provides two helper
classes LatLng and Point to deal with the corresponding methods.
1. isLatLngInside(latlngs, latlng)
2. isPointInside(points, point)
var polygonVertices = [];

polygonVertices.push(new LatLng(28.635789, 77.215029));

polygonVertices.push(new LatLng(28.638086, 77.220952));

polygonVertices.push(new LatLng(28.634621, 77.225758));

polygonVertices.push(new LatLng(28.634771, 77.221467));

polygonVertices.push(new LatLng(28.632662, 77.225114));

polygonVertices.push(new LatLng(28.629724, 77.220265));

polygonVertices.push(new LatLng(28.631796, 77.215265));

var latlng = new LatLng(28.632869, 77.219466);

var isLatLngInside = raycast.isLatLngInside(polygonVertices, latlng);

view rawnodeRcSample.js hosted with

by GitHub

In Depth Explanation. TL;DR


The logical line of thought behind the algorithm is that if I draw a ray (infinitely
long line) from a point it would either never enter a given polygon or will finally
exit it at some point of time. If the point is outside the polygon, a ray from it will
either never enter OR will have one or more enter-exit pairs. Ray from a
point inside the polygon will also finally exit and as it starts from within the
polygon in the first place, it will have an extra exit count.
In other words, take the number of intersections and consider that the last
intersection (if any) is always for an EXIT. If you draw the ENTER-EXIT
sequence backwards, for an odd count the first in the sequence will always be
an EXIT, proving that its a case of point lying inside the polygon. And for an
even count the first in the sequence will always be an ENTER, proving that its
a case of point being outside the polygon.
In the illustration we discussed above, following are the ENTER-EXIT
sequences for the 4 points
Point A

intersections count: 1
Sequence: EXIT
conclusion: Point A is inside the polygon
Point B
intersections count: 0
Sequence:
conclusion: Point B is out the polygon
Point C
intersections count: 2
Sequence: ENTER EXIT
conclusion: Point C is outside the polygon
Point D
intersections count: 3
Sequence: EXIT ENTER EXIT
conclusion: Point D is inside the polygon
It works!

If you find this algorithm useful and interesting, it goes very well with another
computational geometry concept called Voronoi. You might want to take a
look at myblogpost on Voronoi and this npm package.

Source http://vinsol.com/blog/2016/08/04/ray-casting-algorithm/

You might also like