Client side point in polygon
Submitted by admin on Fri, 05/02/2008 - 21:09.
It was needed to implement rather simple operation of finding which of the placemarks in KML file particular GLatLng belongs to. To my surprise, find existing solution was tricky, so I wrote my own, see below. Code in XML parser is somewhat based on Lance Dyas GeoXML's parser.
function fetchRegions(url)
{
GDownloadUrl(url,
function(doc) {
var tree = GXml.parse(doc);
var root = tree.documentElement;
if (!root) {
alert("No regions table found");
return 0;
}
regions = {};
var places = root.getElementsByTagName("Placemark");
for (var i = 0; i < places.length; i++) {
var name = places[i].getAttribute("id");
var poly = places[i].getElementsByTagName("Polygon")[0];
// XXX: we're little bit stupid here, as we only care about
// outer boundary coordinates
var coords = GXml.value(poly.getElementsByTagName("coordinates")[0]);
coords += " ";
coords=coords.replace(/\s+/g," ");
coords=coords.replace(/^ /,"");
coords=coords.replace(/, /,",");
var path = coords.split(" ");
var points = [];
for (var p=0; p<path.length-1; p++) {
var bits = path[p].split(",");
var point = new GLatLng(parseFloat(bits[1]), parseFloat(bits[0]));
points.push(point);
}
regions[name] = points;
}
}
);
}
function inPoly(poly, point)
{
var inside = false;
var npoints = poly.length;
if (npoints < 3) {
return false;
}
var xnew,ynew;
var x1, y1;
var x2, y2;
var xold = poly[npoints-1].lat(), yold=poly[npoints-1].lng();
var xt = point.lat(), yt = point.lng();
for (var i=0 ; i < npoints ; i++) {
xnew=poly[i].lat();
ynew=poly[i].lng();
if (xnew > xold) {
x1=xold; x2=xnew;
y1=yold; y2=ynew;
} else {
x1=xnew; x2=xold;
y1=ynew; y2=yold;
}
if ( (xnew < xt) == (xt <= xold)
&&
((yt-y1)*(x2-x1) < (y2-y1)*(xt-x1)) ) {
inside = !inside;
}
xold=xnew; yold=ynew;
}
return inside;
}
function findRegion(point)
{
var polys = [];
for (var n in regions) {
if (inPoly(regions[n], point)) {
polys.push(n);
}
}
return polys;
}
