2013-09-30 23 views
0

我尝试用coffeescript重写这段代码,来自http://jsfromhell.com/math/is-point-in-poly。它检测一个点是否在一个多边形中,并且工作得很好,但我不确定一个优雅的咖啡文本翻译会是什么样的?如何重写从javascript到coffeescript的更复杂的循环?

function isPointInPoly(poly, pt){ 
    for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) 
    ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) 
    && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y)/(poly[j].y - poly[i].y) + poly[i].x) 
    && (c = !c); 
return c; 
} 
+4

您是否试图首先获得优雅的JavaScript版本? – Bergi

+0

http://js2coffee.org/ – Mathletics

+0

谢谢你的js2coffee.org,这是一个很好的。因为我的问题被授予-1,所以我可能没有清楚地问清我的主要问题是什么:在声明中用重写来重写for循环的适当方法是什么? js2coffee建议的while循环是要走的路吗? –

回答

4

正如比较(双关语意)的一个点,这里是这个算法我几年前写的部分的版本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 

这是比其他版本更多的代码行,但它的优化速度比简洁更多。

+1

它也更清晰。取决于快捷键'||'和'&&'使得代码非常不透明。 – hpaulj

1

我与

isPointInPoly = (poly, pt) -> 
    c = false 
    j = poly.length - 1 
    for b, i in poly 
    a = poly[j] 
    if ((a.y <= pt.y && pt.y < b.y) || (b.y <= pt.y && pt.y < a.y)) && (pt.x < (b.x - a.x) * (pt.y - a.y)/(b.y - a.y) + a.x) 
     c = not c 
    j = i 
    c 

demo compilation)去

+0

@ muistooshort:但是当*有*没有其他循环在那个函数中......你是对的,没有保证,也不应该使用它们。 – Bergi