作为一个比较点(双关语),这是我几年前作为 PolyGonzo(我在 Google 的选举地图中使用的快速多边形绘图库)的一部分编写的该算法的一个版本。这改编自原始版本,它处理地理工作中常用的多面体,而不仅仅是单个多边形。
我写这段代码是为了速度——它应该比旧浏览器问题中的代码快很多,在新浏览器中要快一些。(我已经有一段时间没有对它进行基准测试了,但我怀疑现在浏览器在优化 JavaScript 方面做得更好了,差异会变小。)
例如,它避免了 jsfromhell 示例中使用的所有重复数组和属性取消引用。我认为它也更容易阅读。当然算法本身还是有点复杂的!
function pointInPoly( poly, point ) {
var inside = false,
x = point.x, y = point.y,
n = poly.length,
vertex = poly[ n - 1 ],
x1 = vertex.x, y1 = vertex.y;
for( var i = 0; i < n; ++i ) {
vertex = poly[i];
var x2 = vertex.x, y2 = vertex.y;
if( ( y1 < y ) != ( y2 < y ) )
if( x1 + ( y - y1 ) / ( y2 - y1 ) * ( x2 - x1 ) < x )
inside = ! inside;
x1 = x2, y1 = y2;
}
return inside;
}
我不太喜欢 js2coffee.org 为该代码生成的翻译。特别是,if
循环中的嵌套语句变成了一个很长的单行语句:
inside = not inside if x1 + (y - y1) / (y2 - y1) * (x2 - x1) < x unless (y1 < y) is (y2 < y)
但是很容易将其用作起点并将其变成更好的 CoffeeScript 版本:
pointInPoly = ( poly, point ) ->
inside = false
x = point.x
y = point.y
vertex = poly[ poly.length - 1 ]
x1 = vertex.x
y1 = vertex.y
for vertex in poly
x2 = vertex.x
y2 = vertex.y
if ( y1 < y ) != ( y2 < y )
if x1 + ( y - y1 ) / ( y2 - y1 ) * ( x2 - x1 ) < x
inside = not inside
x1 = x2
y1 = y2
inside
这比其他版本多几行代码,但它再次优化速度而不是简洁。